带你快速了解jwt

    科技2024-01-20  89

    愿你生命中有够多的云翳,造就一个美好的黄昏 

     

    欢迎关注公众号【渣男小四】,一个喜欢技术更喜欢艺术的青年

     

    一.介绍

     

      JWT是JSON Web Token 的简写,Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密

     

    二.为什么要用JWT

      随着互联网技术的不断革新以及人们使用互联网的频率越来越高,网站人数日趋增长,这样给服务器带来了巨大的压力,在传统的互联网架构中,使用session(会话)来作为标识用户的凭证,当用户登录系统后,一般将用户的账号,角色等信息存在session会话中,然后返回客户端,将session存在客户端的Cookie中,这样用户再次请求的时候就带上Cookie里的session_id,与之前的校验,但是这样有很大的弊端,我们知道session它存在服务器端(试想一下如果百万上千万的session同时存在于服务器,那服务器所承受的压力是很大的,当然,没有那个公司到达这个规模还用session,这东西过时了),使用session的弊端还在于它无法满足分布式系统的需求,当然也可以通过Redis这种缓存技术对分布式session进行管理,但是这样工作量比较大,如果持久层挂了,那么单点登录就失败,所有就引入了JWT

     

    三.JWT原理

      服务器认证以后,生成一个 JSON 对象,发回给用户,此后每次请求都会再请求头带上它,类似下面

    { " 用户名":"steak" "角色" :"管理员" "到期时间":"2019.12.2" }

      用JWT认证后,服务端就变成无状态了,更加容易扩展(分布式)

     

    四.JWT的组成部分

      1.Header:头部

      2.payload:负载

      3.Signature:签名

      三部分连起来就类似这个样子

       Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

    { "alg": "HS256", //签名算法 "typ": "JWT" //令牌(token)的类型 }

      Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,也可以自定义字段

    iss (issuer):签发人   exp (expiration time):过期时间   sub (subject):主题   aud (audience):受众   nbf (Not Before):生效时间   iat (Issued At):签发时间   jti (JWT ID):编号 { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }

      Signature 部分是对Header,payload两部分的签名,防止数据篡改,需要指定一个密钥(secret),这个密钥只有服务器才知道,不能泄露给用户,然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

    HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret )

      Header和payload都是使用Base64URL进行加密

     

    五.使用

      当用户登录后,会将用户的信息进行加密,然后返回客户端一个加密后的字符串,可以存储在客户端的Cookie里,此后每一次请求都会带上它(放在请求头),如果此字符串和服务端的一致,则认证成功,否则失败,最好放在请求头里面,否则跨域带不过去。

     

    六.代码

    pom.xml

    <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.3</version> </dependency> <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>

    创建jwt

    //创建jwt PayloadConstant.SECRET为密钥 public static String createJWT(long expirationDate , User user){ //签名算法 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //生成Jwt时间 long jwtTime = System.currentTimeMillis(); Date date = new Date(jwtTime); //创建payload私有声明 Map<String,Object> map = new HashMap<>(); map.put("userId",user.getUserId()); map.put("userName",user.getUserName()); map.put("password",user.getPassword()); map.put("role",user.getRole()); //签发人 String subject = user.getUserName(); //为payload添加各种标准 JwtBuilder jwtBuilder = Jwts.builder().setClaims(map) .setId(UUID.randomUUID().toString().replace("_","")) .setIssuedAt(date) .setSubject(subject) .signWith(signatureAlgorithm,PayloadConstant.SECRET); if (expirationDate >= 0){ long expDate = jwtTime + expirationDate; Date exp = new Date(expDate); //设置过期日期 jwtBuilder.setExpiration(exp); } return jwtBuilder.compact(); }

    验证jwt是否有效

    /** * 判断jwt是否有效 * @param token * @return */ public R checkToken(String token) { try { //正常 return Jwts.parser().setSigningKey(PayloadConstant.SECRET).parseClaimsJws(token).getBody(); }catch (Exception e){ //无效 return null; } }

     

    Processed: 0.013, SQL: 8