springboot集成json web token

     jwt已经更新好几版本了,也是取代cookie的方式之一。感觉用起来还是蛮简单的,废话不多讲,直接上代码集成的核心代码。

一、jar引入

<dependency>
   <groupId>io.jsonwebtoken</groupId>
   <artifactId>jjwt</artifactId>
   <version>0.9.1</version>
</dependency>
<dependency>
   <groupId>com.auth0</groupId>
   <artifactId>java-jwt</artifactId>
   <version>3.8.3</version>
</dependency>    

二、WebMvcConfigurer设置。

     增加拦截器拦截器,具体:

@Override
public void addInterceptors(InterceptorRegistry registry) {
    //接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。
    //这个方法是去读取配置文件里配置的不校验token的请求,比如登录不校验
    initPassUrl();
    registry.addInterceptor(new HandlerInterceptorAdapter(){
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String url = request.getRequestURI();
            log.info("----请求的url:{}",url);
//Option类型请求不校验
            if(isOptionRequest(request)){
                response.setStatus(200);  
                return true;
            }
            if(isTokenCheckPassUrl(request)){
                log.info("---不校验token的请求");
                return true;
            }
//以什么开头的不校验
            if (!url.startsWith("/sysMobile")){
                log.debug("---PC端接口暂时不校验token");
                return true;
            }
            //jwt token认证处理
            boolean pass = jwtTokenAuthentication(request);
            if (pass) {
                /// 反向获取用户信息  设置用户信息
                //request.setAttribute("", "");
                log.info("---jwt校验通过");
                return true;
            } else {
                log.warn("token认证失败,请求接口:{},请求IP:{},请求参数:{}",
                        request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));

                Result result = new Result();
                result.setCode(ResultCode.UNAUTHORIZED).setMessage("请求认证无权限或认证失败");
                responseResult(response, result);
                return false;
            }
        }
    });
    
}

三、我的jwt的工具类(关键方法)

/**
 * 内部類
 */
static class TokenValidationException extends RuntimeException {
    public TokenValidationException(String msg) {
        super(msg);
    }
}

/**
 * 手机端运营,生成token
 * @param loginUserDto 登录用户
 * @return
 */
public static String mobileSysGenerateToken(SysOrgUserDto loginUserDto) {
    Long expSeconds = LocalHostUtil.getMobileSysLoginTokenExp();
    //为空默认1小时
    if (expSeconds == null){
        expSeconds = 3600L;
    }
    Date iaDate = new Date();
    Calendar nowTime = Calendar.getInstance();
    nowTime.add(Calendar.MINUTE,1);
    Calendar expiresDate = Calendar.getInstance();
    expiresDate.add(Calendar.SECOND,expSeconds.intValue());
    Map<String,Object> map = new HashMap<>(3);
    map.put("alg","HS256");
    map.put("typ","JWT");
    String token = JWT.create().withHeader(map)
            .withClaim(USER_NAME,loginUserDto.getUserName())
            .withClaim(ORG_CODE,loginUserDto.getOrgCode())
            .withExpiresAt(expiresDate.getTime())
            .withIssuedAt(iaDate)
            .sign(Algorithm.HMAC256(SECRET));

    //jwt前面一般都会加Bearer
    return TOKEN_PREFIX + token;
}

/**
 * 手机运营端,验证token
 * @param token
 * @return
 */
public static boolean validateTokenAndAddUserIdToHeader(String token) {
    JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
    DecodedJWT jwt = null;
    Map<String, Claim> claims = null;
    try {
        jwt = verifier.verify(token.replace(TOKEN_PREFIX, ""));
        claims = jwt.getClaims();
        if (!CollectionUtils.isEmpty(claims)){
            String tokenUserName = claims.get(USER_NAME).asString();
            String tokenOrgCode = claims.get(ORG_CODE).asString();
            log.info("---token用户信息--公司code:{},用户名:{}",tokenOrgCode,tokenUserName);
            Date expDate = jwt.getExpiresAt();
            Date now = new Date();
            if (now.before(expDate)){
                log.info("----jwt token有效");
                return true;
                //throw new TokenValidationException("登陆凭证已过期,请重新登陆!");
            }
        }
        return false;
    }catch (Exception e){
        if (CollectionUtils.isEmpty(claims)){
            log.info("用户{}token已经过期,登录参数为空,需要重新登陆!");
        }else{
            log.info("用户{}token已经过期,需要重新登陆!",claims.get("name").asString());
        }
        //throw new TokenValidationException("登陆凭证已过期,请重新登陆!");
        return false;
    }
}

上面一个是生成token,一个是验证token。我这里设计的是登录成功后,调用生成token,返回给前端,前端缓存,以后请求在head里设置token。这里的验证,会校验生成时设置的有效期。

     使用就是这么简单,但是这个感觉也有弊端,因为生成的token是按照withClaim设置的顺序生成的,所以同一个用户,每次生成的token,前面几节可能是一样的,如果知道这个的人,可能可以把你的密匙试出来。加班时间到了,就写道这里吧。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥仔哥哥1930

来一波支持,吃不了亏上不了当

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值