21-JWT令牌认证与置换

JWT令牌的认证与置换

令牌的产生是在具有登录服务的微服务上,而令牌的校验是在网关服务上对其进行校验

img

网关校验JWT
在网关过滤器IdentityAuthFilter中
    /**
     * 具体的过滤器规则
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("执行过滤方法");
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //从Http Header中,判断是否有authentication的存在
        String authentication = request.getHeader("authentication");
        if(StringUtils.hasLength(authentication)){
            //有长度,暂时默认成功
            System.out.println("进入到微服务");
            System.out.println(authentication);
            //当获取的令牌以后,Zuul需要对Token做一个身份识别
            validateTokenLegal(authentication,requestContext);

        }else{//如果没有长度,或者为NULL,设置响应失败(401)
            handlerIllegalToken(requestContext,HttpStatus.UNAUTHORIZED.value(),
                    ResponseMsg.builder().code(10001).msg("未认证,请登录!").build());
        }

        return null;
    }

    /**
     * 处理非常令牌
     * @param requestContext
     * @param status
     * @param responseMsg
     */
    public void handlerIllegalToken(RequestContext requestContext,int status,ResponseMsg responseMsg){
        //不进入到下一步(route过滤器)
        requestContext.setSendZuulResponse(false);

        //设置响应数据
        HttpServletResponse response = requestContext.getResponse();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        requestContext.setResponse(response);
        requestContext.setResponseStatusCode(status);
        requestContext.setResponseBody(JSONObject.toJSONString
                (responseMsg));
    }

    /**
     * 用于识别Token令牌是否合法
     * @param authentication
     * @param requestContext
     */
    private void validateTokenLegal(String authentication, RequestContext requestContext) {
        //创建一个JWT的验证实例
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(JWTUtil.SECURITY)).build();

       try{
           //该方法就是针对令牌做校验
           DecodedJWT decodedJWT = verifier.verify(authentication);

           //更新令牌
		   




       } catch (Exception e){
           e.printStackTrace();
           //令牌的算法错误
           if(e instanceof AlgorithmMismatchException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10003).msg("非法令牌,无法识别!").build());
           //令牌已失效
           }else if(e instanceof TokenExpiredException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10004).msg("令牌已过期,请重新登录!").build());
           //令牌是非法令牌
           }else if(e instanceof SignatureVerificationException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10005).msg("非法令牌,无法识别!").build());
           }else{
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10006).msg("未知错误!").build());
           }
       }
    }
令牌的刷新

原理:前端发起的每次请求,后端都给它置换一个新的令牌的信息


    /**
     * 用于识别Token令牌是否合法
     * @param authentication
     * @param requestContext
     */
    private void validateTokenLegal(String authentication, RequestContext requestContext) {
        //创建一个JWT的验证实例
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(JWTUtil.SECURITY)).build();

       try{
           //该方法就是针对令牌做校验
           DecodedJWT decodedJWT = verifier.verify(authentication);

           //更新令牌
           Map<String,Object> claims = new HashMap<>();
           String loginName = decodedJWT.getClaim("loginName").as(String.class);
           claims.put("loginName",loginName);

           String newToken = JWTUtil.createToken(claims);
           //获取到响应对象
           HttpServletResponse response = requestContext.getResponse();
           response.setHeader("token",newToken);
       } catch (Exception e){
           e.printStackTrace();
           //令牌的算法错误
           if(e instanceof AlgorithmMismatchException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10003).msg("非法令牌,无法识别!").build());
           //令牌已失效
           }else if(e instanceof TokenExpiredException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10004).msg("令牌已过期,请重新登录!").build());
           //令牌是非法令牌
           }else if(e instanceof SignatureVerificationException){
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10005).msg("非法令牌,无法识别!").build());
           }else{
               handlerIllegalToken(requestContext,HttpStatus.FORBIDDEN.value(),
                       ResponseMsg.builder().code(10006).msg("未知错误!
                                                             ").build());
           }
       }
    }

核心置换代码:

image-20210106105436310

思考:

1、如果现在说所有的终端,当有1个终端在线时,其他终端就无法登陆?

答案:将Token统一位置存储,每个人单位时间针对所有的终端,只能存在一个终端的Token信息。

当然,上述的问题,需要配合Redis来实现

2、如果假设有人将你的Token获取到了,模拟你操作,后端如何保证敏感数据的安全性?

答案:短信验证,支付密码,短期令牌(1分钟),人脸识别

终端就无法登陆?

答案:将Token统一位置存储,每个人单位时间针对所有的终端,只能存在一个终端的Token信息。

当然,上述的问题,需要配合Redis来实现

2、如果假设有人将你的Token获取到了,模拟你操作,后端如何保证敏感数据的安全性?

答案:短信验证,支付密码,短期令牌(1分钟),人脸识别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值