Java安全验证之jwt(json web token)

刺骨的言语ヽ痛彻心扉 2022-06-10 05:10 444阅读 0赞

http://blog.csdn.net/u012017645/article/details/53585872

jwt token安全验证流程:用户发起登录请求,服务端创建一个加密后的jwt信息,作为token返回值,在后续请求中jwt信息作为请求头,服务端正确解密后可获取到存储的用户信息,表示验证通过;解密失败说明token无效或者已过期。

jwt token的组成:header.poyload.sign

  • header:头部,主要包括参数的类型—JWT,加密算法—-RS512,头部由json字符串用base64编码生成;
  • poload:载荷,存放需要保存的一些用户信息,主要包括主题、签发者、接受者、到期时间等,载荷也由json字符串用base64编码生成,不能存放敏感数据;
  • sign:签名,防止恶意篡改数据。

依赖:

  1. <!-- 使用JWT在用户和服务器之间传递安全可靠的信息 -->
  2. <dependency>
  3. <groupId>io.jsonwebtoken</groupId>
  4. <artifactId>jjwt</artifactId>
  5. <version>0.6.0</version>
  6. </dependency>

jwt加解密的工具类:

  1. package cn.lsh.util;
  2. import java.security.Key;
  3. import java.util.Date;
  4. import javax.crypto.spec.SecretKeySpec;
  5. import javax.xml.bind.DatatypeConverter;
  6. import io.jsonwebtoken.Claims;
  7. import io.jsonwebtoken.JwtBuilder;
  8. import io.jsonwebtoken.Jwts;
  9. import io.jsonwebtoken.SignatureAlgorithm;
  10. import org.apache.commons.lang.exception.ExceptionUtils;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;
  13. import cn.lsh.entity.User;
  14. import cn.lsh.vo.security.Audience;
  15. import cn.lsh.vo.security.LoginParamter;
  16. public class JwtUtils {
  17. private static final Logger LOGGER=LoggerFactory.getLogger(JwtUtils.class);
  18. private JwtUtils(){
  19. }
  20. /*
  21. * 验证jwt是否合法,即解密
  22. */
  23. public static Claims parseJWT(String jsonWebToken,String base64Security){
  24. try {
  25. return Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
  26. .parseClaimsJws(jsonWebToken)
  27. .getBody();
  28. } catch (Exception e) {
  29. // TODO: handle exception
  30. LOGGER.error("exception message is: {}", ExceptionUtils.getStackTrace(e));
  31. return null;
  32. }
  33. }
  34. /*
  35. * 创建jwt,即加密
  36. */
  37. public static String createJWT(LoginParamter loginParamter,User user,Audience audience){
  38. long ttlmillis=audience.getExpiresSecond()*1000;
  39. String base64Security=audience.getBase64Secret();
  40. Date now=new Date(System.currentTimeMillis());
  41. //生成签名密钥
  42. byte[] apiKeySecretBytes=DatatypeConverter.parseBase64Binary(base64Security);
  43. Key signingKey=new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
  44. //添加构成JWT的参数
  45. JwtBuilder builder=Jwts.builder().setHeaderParam("typ", "JWT")//typ表示token的类型
  46. .claim("role", user.getRole())// 自定义属性
  47. .claim("unique_name", loginParamter.getUserName())
  48. .claim("userid", user.getName())
  49. .setIssuer(audience.getName())// 签发者
  50. .setAudience(audience.getClientId())//接受者
  51. .signWith(SignatureAlgorithm.HS256, signingKey);// 签名算法以及密匙
  52. //添加Token过期时间
  53. if(ttlmillis>=0){
  54. Date exp=new Date(System.currentTimeMillis()+ttlmillis);
  55. builder.setExpiration(exp)// 过期时间
  56. .setNotBefore(now);// 失效时间
  57. }
  58. //生成JWT
  59. return builder.compact();
  60. }
  61. public static void main(String[] args) {
  62. Claims c=parseJWT("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoi566h55CG5ZGYIiwidW5pcXVlX25hbWUiOiJsaXVzaGlodWEiLCJ1c2VyaWQiOiJsaXVzaGlodWEiLCJpc3MiOiJsaXVzaGlodWEiLCJhdWQiOiIwOThmNmJjZDQ2MjFkMzczY2FkZTRlODMyNjI3YjRmNiIsImV4cCI6MTUwMjM1OTQ1NSwibmJmIjoxNTAyMzUyMjU0fQ.OeDN4deNUlDiUmwROjxw5_xrurJt46b1RZ0K5yNKH88",
  63. "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=");
  64. System.out.println(c);
  65. }
  66. }

audience包含token的一些信息:

  1. package cn.lsh.vo.security;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import org.springframework.boot.context.properties.ConfigurationProperties;
  5. import org.springframework.stereotype.Component;
  6. import lombok.Data;
  7. @Data
  8. //绑定属性的配置信息到该bean中,配置信息前缀为audience
  9. @ConfigurationProperties(prefix="audience")
  10. @Component
  11. @ApiModel(value="JWT")
  12. public class Audience {
  13. @ApiModelProperty(value="传入的客户端id,相当于微信的openID",required=true)
  14. private String clientId;
  15. @ApiModelProperty(value="64位公钥",required=true)
  16. private String base64Secret;
  17. @ApiModelProperty(value="令牌发行者姓名",required=true)
  18. private String name;
  19. @ApiModelProperty(value="令牌有效时间,单位为秒",required=true)
  20. private int expiresSecond;
  21. }

一、在用户登录是生成token,返回给客户端

  1. String accessToken=JwtUtils.createJWT(loginParamter, user, audience);

二、在用户下次请求是验证token

  1. private boolean isValidJwt(HttpServletRequest request){
  2. LOGGER.info("{} request to {}",request.getMethod(),request.getRequestURL());
  3. String authorization=request.getHeader("Authorization");
  4. LOGGER.info("authorization is: {}",authorization);
  5. //access_token的头信息,定义为bearer
  6. String headString=authorization.substring(0, 6).toLowerCase();
  7. //compareTo逐个比较两个字符串中相对字符的ascll值,所有字符都相同返回0,发现小于时返回正整数,大于时返回负整数,即ascll值的差值。
  8. if(headString.compareTo(Constants.BEARER)==0){
  9. authorization=authorization.substring(6, authorization.length());
  10. if(JwtUtils.parseJWT(authorization, audience.getBase64Secret())!=null){
  11. return true;
  12. }
  13. }
  14. return false;
  15. }

发表评论

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

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

相关阅读

    相关 用户登录token验证

    1.场景还原      可能还有很多小伙伴对token概念朦朦胧胧,今天笔者以项目中的用户登录的token验证需求跟大家讲讲其中的来龙去脉,希望能够理清大伙的思路。

    相关 javaToken验证

    突然发现这篇博文的浏览器已经破三千了,我觉得还是有必要提一下,在实际的工作项目中,如果采用这种方法的话, 可能代码量会比较多,很繁琐,但优点是对于新人可能是更好的去理解吧(

    相关 HAP框架Token验证

    闲来无事,总结这几天遇到的一个问题,以及解决过程。 这几天在做一个考核项目,拿到需求以后,那就敲代码啊。敲完一个修改功能的时候,测试的时候,突然跳出来这样一个提示框。 ![