分布式session解决方案 — — JWT(生成token)

阳光穿透心脏的1/2处 2024-04-08 12:50 129阅读 0赞

JWT 跨域认证解决方案

1 介绍

  • JWT(JSON Web Token)是目前最流行的跨域认证解决方案,是一种基于Token的认证授权机制,JWT本身也是Token,是一种规范化之后的JSON结构的Token。
  • JWT自身包含了验证所需要的所有信息,因此,我们的服务器不需要存储Session信息(其他解决方案:hash、session共享),增加了系统的可用性和伸缩性,大大减轻了服务端的压力。
  • JWT更符合RESTFul API的无状态原则
  • JWT认证可以有效避免CSRF(跨站请求伪造攻击),因为JWT一般是存在在localStorage中,使用JWT进行身份验证的过程中不会涉及到Cookie

2 组成部分

JWT本质就是一组字符串,通过(.)切分成三个为Base64编码的部分:

  1. Header:描述JWT元数据,定义生成签名的算法及Token类型
  2. Payload:存放实际要传递的数据
  3. Signature(签名):服务器通过Payload、Header和一个密钥(Secret)使用Header里面指定的签名算法(默认是HMAC SHA256)

实例:用点分割,分为三部分
在这里插入图片描述

3 JWT工具类的编写(企业开发)

3.1 定义对应编码及盐值(加密时)

  1. //定义对应的编码算法
  2. static SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
  3. //盐值,盐值随意,看公司要求【此处我采用UUID】
  4. static String secretKey = "d8de020f63754a9fa746ea74b831afc3";

3.2 获取key

  1. //获取key(指定算法和盐值的key对象)
  2. private static Key generateKey(){
  3. //将盐值转成字节
  4. byte[] bytes = DatatypeConverter.parseBase64Binary(secretKey);
  5. //根据算法和盐值生成对应的key值
  6. Key key = new SecretKeySpec(bytes, signatureAlgorithm.getJcaName());
  7. return key;
  8. }

3.3 生成token(generatorToken)

  1. /**
  2. * 将我们的数据使用JWT的方式变成一个token xxx.yyy.zzz
  3. * @param payLoad 负载(数据信息)
  4. * @return
  5. */
  6. public static String generatorToken(Map<String, String> payLoad){
  7. ObjectMapper objectMapper = new ObjectMapper();
  8. try{
  9. //构建jwt生成器
  10. JwtBuilder builder = Jwts.builder();
  11. //将负载信息设置到jwt生成器中
  12. JwtBuilder jwtBuilder = builder.setPayload(objectMapper.writeValueAsString(payLoad));
  13. //根据签名算法和key值,生成新的jwtBuilder
  14. JwtBuilder jwtBuilder1 = jwtBuilder.signWith(signatureAlgorithm, generateKey());
  15. String token = jwtBuilder1.compact();
  16. return token;
  17. } catch (JsonProcessingException e) {
  18. e.printStackTrace();
  19. }
  20. return null;
  21. }

3.4 获取token中的body信息

  1. /**
  2. * 根据指定的token, 返回对应的body信息
  3. * @param token
  4. * @return
  5. */
  6. public static Claims phaseTokenGetBody(String token){
  7. JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
  8. Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
  9. Claims body = claimsJws.getBody();//主要存放的信息
  10. return body;
  11. }

3.5 获取token中的signature信息

  1. /**
  2. * 根据指定的token获取签名信息
  3. * @param token
  4. * @return
  5. */
  6. public static String phaseTokenGetSignature(String token){
  7. JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
  8. Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
  9. String signature = claimsJws.getSignature();
  10. return signature;
  11. }

3.6 获取token中的头信息

  1. /**
  2. * 根据指定的token获取头信息
  3. * @param token
  4. * @return
  5. */
  6. public static JwsHeader phaseTokenGetHeader(String token){
  7. //获取解析器
  8. JwtParser parser = Jwts.parser();
  9. //设置签名key(盐值)
  10. parser = parser.setSigningKey(generateKey());
  11. //解析token
  12. Jws<Claims> claimsJws = parser.parseClaimsJws(token);
  13. JwsHeader header = claimsJws.getHeader();
  14. return header;
  15. }

3.7 测试

①在map中存入自己的数据,调用自定义API生成对应token

  1. public static void main(String[] args) {
  2. //随机获取盐值
  3. // System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
  4. Map<String, String> payLoad = new HashMap<>();
  5. payLoad.put("name", "curry");
  6. String s = generatorToken(payLoad);
  7. //eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiY3VycnkifQ.Sf3GiF3p56nLzoAxEHLXcAckPmmPTtecj1_lGT9oV8s
  8. System.out.println(s);
  9. }

②在jwt官网https://jwt.io/中进行解析,也可以调用自己的API进行解析
在这里插入图片描述
调用自己API:

  1. //调用自定义API获取结果
  2. Claims claims = phaseTokenGetBody(s);
  3. //{name=curry}

③如果所给token有误,则会报错

  1. Exception in thread "main" io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

4 全部代码包含测试

  1. package com.zi.api.commons.util;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import io.jsonwebtoken.*;
  5. import javax.crypto.spec.SecretKeySpec;
  6. import javax.xml.bind.DatatypeConverter;
  7. import java.security.Key;
  8. import java.util.HashMap;
  9. import java.util.Map;
  10. /**
  11. * 生成jwt工具类
  12. */
  13. public class JJWTRootUtils {
  14. //定义对应的编码算法
  15. static SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
  16. //盐值
  17. static String secretKey = "d8de020f63754a9fa746ea74b831afc3";
  18. //获取key(指定算法和盐值的key对象)
  19. private static Key generateKey(){
  20. //将盐值转成字节
  21. byte[] bytes = DatatypeConverter.parseBase64Binary(secretKey);
  22. //根据算法和盐值生成对应的key值
  23. Key key = new SecretKeySpec(bytes, signatureAlgorithm.getJcaName());
  24. return key;
  25. }
  26. /**
  27. * 将我们的数据使用JWT的方式变成一个token xxx.yyy.zzz
  28. * @param payLoad 负载(数据信息)
  29. * @return
  30. */
  31. public static String generatorToken(Map<String, String> payLoad){
  32. ObjectMapper objectMapper = new ObjectMapper();
  33. try{
  34. //构建jwt生成器
  35. JwtBuilder builder = Jwts.builder();
  36. //将负载信息设置到jwt生成器中
  37. JwtBuilder jwtBuilder = builder.setPayload(objectMapper.writeValueAsString(payLoad));
  38. //根据签名算法和key值,生成新的jwtBuilder
  39. JwtBuilder jwtBuilder1 = jwtBuilder.signWith(signatureAlgorithm, generateKey());
  40. String token = jwtBuilder1.compact();
  41. return token;
  42. } catch (JsonProcessingException e) {
  43. e.printStackTrace();
  44. }
  45. return null;
  46. }
  47. /**
  48. * 根据指定的token, 返回对应的body信息
  49. * @param token
  50. * @return
  51. */
  52. public static Claims phaseTokenGetBody(String token){
  53. JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
  54. Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
  55. Claims body = claimsJws.getBody();//主要存放的信息
  56. return body;
  57. }
  58. /**
  59. * 根据指定的token获取签名信息
  60. * @param token
  61. * @return
  62. */
  63. public static String phaseTokenGetSignature(String token){
  64. JwtParser jwtParser = Jwts.parser().setSigningKey(generateKey());
  65. Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
  66. String signature = claimsJws.getSignature();
  67. return signature;
  68. }
  69. /**
  70. * 根据指定的token获取头信息
  71. * @param token
  72. * @return
  73. */
  74. public static JwsHeader phaseTokenGetHeader(String token){
  75. //获取解析器
  76. JwtParser parser = Jwts.parser();
  77. //设置签名key(盐值)
  78. parser = parser.setSigningKey(generateKey());
  79. //解析token
  80. Jws<Claims> claimsJws = parser.parseClaimsJws(token);
  81. JwsHeader header = claimsJws.getHeader();
  82. return header;
  83. }
  84. public static void main(String[] args) {
  85. //随机获取盐值
  86. // System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
  87. Map<String, String> payLoad = new HashMap<>();
  88. payLoad.put("name", "curry");
  89. String s = generatorToken(payLoad);
  90. //eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiY3VycnkifQ.Sf3GiF3p56nLzoAxEHLXcAckPmmPTtecj1_lGT9oV8s
  91. System.out.println(s);
  92. //调用自定义API获取结果
  93. Claims claims = phaseTokenGetBody(s);
  94. //{name=curry}
  95. System.out.println(claims);
  96. }
  97. }

发表评论

表情:
评论列表 (有 0 条评论,129人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Cookie、SessionTokenJWT

    什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明 “你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入

    相关 JWT生成Token

            最近在做登录功能,项目是前后端完全分离,就想到了使用jwt。下面是一些参考资料,整理了一下jwt,单点登录sso,以及session/cookie,感兴趣的可以