0
点赞
收藏
分享

微信扫一扫

单点登录和JWT的介绍与使用

前言:最近复习之前做的项目中包含的知识,看了之前看的视频的笔记,并结合自己的理解写下了这篇关于JWT知识的博客,希望能加深自己的印象以及帮助的诸位小伙伴儿们🤞🤞
如果有什么需要改进的地方还请大佬斧正😁
小威在此先感谢诸佬了👏👏
在这里插入图片描述

牛客部分使用反馈,个人感觉还不错,帮我找到了心仪的公司,希望各位伙伴儿们通过它也能提高不少🥂🥂🥂

以下正文开始
在这里插入图片描述

文章目录

单点登录三种方式

单点登录的三种实现方式:分别为session广播机制;cookie+redis;token三种。session广播机制指在一个集群中的一个模块登录后,然后把该session复制成几份,发送到该集群的其他模块中,可以形成在个地方登录,其他地方不用再登录的效果。

session广播机制

参与集群的每个节点的Session状态都被复制到集群中的其他所有节点上,无论何时,只要Session发生改变,Session数据都要重新被复制。Tomcat、JBoss等都提供了这样的功能,其中Tomcat采用集群节点广播复制,JBoss采用配对复制机制。

cookie+redis方式

用户在项目的任意一个模块登录后,登录之后,该模块会将用户的登录信息放到两个地方:redis 和 cookie 中。

系统会先将用户的登录信息存入 redis中,其在 redis 的 key 值是生成的唯一值 (可以包含 ip、用户 id、UUID等),value 值存放用户的登录信息。
接着系统会将这名用户在 redis 中的 key 值存入该用户的 cookie 中,用户每次访问任意模块时都会带着这个 cookie。
用户在访问其他模块发送请求时,会带着客户端的 cookie 进行请求,而客户端的 cookie 已经存入了该用户在 redis 中的 key 值,这样其他模块在处理用户的请求时,可以先获取用户 cookie中的 key 值,然后拿着这个 key 值到 redis 中进行查询,如果在 redis 中能查询到该用户相应的登录信息,就说明该用户已登录,就不需要用户进行重复登录了。

token方式

token 是按照一定规则生成的字符串,字符串中可以包含用户信息。开发人员可以自行定制这个生成规则,也可以使用提供好的生成规则(如使用 JWT 自动生成包含用户信息的字符串)。

用户在项目的某个模块进行登录后,系统会按照一定(或定制)的规则生成字符串,把用户登录之后的信息包含到这个生成的字符串中,然后系统可以将这个字符串返回,主要有两种返回方式:1.可以把字符串通过 cookie 返回;2.可以把字符串通过地址栏返回。

这样用户在访问其他的模块时,每次访问的地址栏都会带着生成的字符串在这里插入图片描述
成字符串),然后根据字符串获取用户信息,如果可以获取到用户的登录信息,说明该用户已登录,用户就不需要重复登录了。

JWT令牌介绍

JWT头

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

{
“alg”: “HS256”,
“type”: “JWT”
}
在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);type属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

有效载荷

有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择:

iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,如下例:

{
  "sub": "1234567890",
  "name": "xiaowei",
  "admin": true
}

默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。

JSON对象也使用Base64 URL算法转换为字符串保存。

签名哈希

签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。

首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
在这里插入图片描述

JWT如何使用

JWT的原则
JWT的原则是在服务器身份验证之后,将生成一个JSON对象并将其发送回用户,如下所示。

{
  "sub": "1234567890",
  "name": "xiaowei",
  "admin": true
}

之后,当用户与服务器通信时,客户在请求中发回JSON对象。服务器仅依赖于这个JSON对象来标识用户。为了防止用户篡改数据,服务器将在生成对象时添加签名。

服务器不保存任何会话数据,即服务器变为无状态,使其更容易扩展。

JWT的用法
客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。

此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。当跨域时,也可以将JWT被放置于POST请求的数据主体中。
在这里插入图片描述

JWT的用处

在这里插入图片描述

整合JWT令牌

首先在项目中添加依赖:

<dependencies>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
    </dependency>
</dependencies>

创建JWT的工具类

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm; 
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

public class JwtUtils {
 public static final long EXPIRE = 1000 * 60 * 60 * 24;
 public static final String APP_SECRET = "zkdlh8Ycvxmwd9sDxzc8czxcascX9";
 
 public static String getJwtToken(String id, String nickname){
 
 String JwtToken = Jwts.builder()
 
 .setHeaderParam("type", "JWT")
 
 .setHeaderParam("alg", "HS256")
 
 .setSubject("guli-user")
 
 .setIssuedAt(new Date())
 
 .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
 
 .claim("id", id)
 
 .claim("nickname", nickname)
 
 .signWith(SignatureAlgorithm.HS256, APP_SECRET)
 
 .compact();
 
 
 return JwtToken;
 
 }
 
 /**
 
 * 判断token是否存在与有效
 
 * @param jwtToken
 
 * @return
 
 */
 
 public static boolean checkToken(String jwtToken) {
 
 if(StringUtils.isEmpty(jwtToken)) return false;
 
 try {
 
 Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
 
 } catch (Exception e) {
 
 e.printStackTrace();
 
 return false;
 
 }
 
 return true;
 
 }
  
 /**
 
 * 判断token是否存在与有效
 
 * @param request
 
 * @return
 
 */
 
 public static boolean checkToken(HttpServletRequest request) {
 
 try {
 
 String jwtToken = request.getHeader("token");
 
 if(StringUtils.isEmpty(jwtToken)) return false;
 
 Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
 
 } catch (Exception e) {
 
 e.printStackTrace();
 
 return false;
 
 } 
 return true; 
 }
 
 
 /**
 
 * 根据token获取id
 
 * @param request
 
 * @return
 
 */
 
 public static String getMemberIdByJwtToken(HttpServletRequest request) {
 
 String jwtToken = request.getHeader("token");
 
 if(StringUtils.isEmpty(jwtToken)) return "";
 
 Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
 
 Claims claims = claimsJws.getBody();
 
 return (String)claims.get("id");
 
 }
 
}

文章到这里就结束了,以后还会记录一些其他的知识,喜欢的大佬可以多多支持哦😉😉。
如果有什么疑问的地方请指出,诸佬们一起讨论🍻🍻
在这里插入图片描述

再次感谢各位小伙伴儿们的支持🤞
在这里插入图片描述

举报

相关推荐

0 条评论