jwt生成解析token-简单版

jwt是什么
在这里插入图片描述jwt结构
在这里插入图片描述jwt工具类 生成token和解析校验token

public class jwtUtil {
    //秘钥加密解密都需要用到,所以定义成静态常量
    public static final String SIGNATURE = "miyao";

       /*测试生成jwt的token令牌三部分组成
     . header(加密算法,类型) 
     . payload(负载,可以不重要可以用得到的用户信息) 
     . signature(签名,前两部跟base64加密和自己的秘钥)*/
    /**
     * 生成token
     *
     * @param map payload中需要放置的相关非敏感信息
     * @return 返回的生成的token信息
     */
    public static String getToken(Map<String, String> map) {
        //设置一个时间,作为令牌的过期时间 ,设置过期时间为7天
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);

        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();
        //生成jwt的 [header payload signature]  三部分数据
        //遍历map集合,将传递过来的需要放在jwt中的信息放到payload中
        map.forEach((k, v) -> {
            builder.withClaim(k, v);  //payload信息
        });
        //header信息可以省略,因为默认已经有算法和类型了,也可以在headerMap中设置算法
        HashMap<String, Object> headerMap = new HashMap<>();
        String token = builder.withHeader(headerMap)     //header信息
                .withExpiresAt(calendar.getTime()) //token过期时间
                .sign(Algorithm.HMAC256(SIGNATURE));//签名
        return token;
    }

    /**
     * 验证token DecodedJWT 为解密之后的对象 可以获取payload中添加的数据
     */
    public static DecodedJWT verifyToken(String token) {
        //进行token的校验,注意使用同样的算法和同样的秘钥
        return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
    }
}

设置拦截器,在方法执行前调用工具类中的token解析方法,进行token校验

/**
 * 添加拦截器,拦截请求,校验token
 */
public class JWTInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        String token = request.getHeader("token");  //从request中获取到请求头中的token,进行解析校验
        try {
            jwtUtil.verifyToken(token);//调用token解析的工具类进行解析,没有异常说明获取成功
            return true;  //请求放行
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msg", "签名不一致异常");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg", "令牌过期异常");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg", "算法不匹配异常");
        } catch (InvalidClaimException e) {
            e.printStackTrace();
            map.put("msg", "失效的payload异常");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效");
        }
        //map异常的数据要返回给客户端需要转换成json格式  @ResponseBody 内置了jackson
        String resultJson = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().print(resultJson);
        return false;  //异常不放行
    }
}

设置拦截器的拦截规则

@Configuration
public class interceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/interceptorVerify/**")   //拦截所有的路径
                .excludePathPatterns("/login/**"); //放行login目录下的,因为生成token拦截就无法生成了
    }
}

controller代码

@RestController
    public class JWTTokenApplication {

    /**
     * 用户登录的接口,校验数据库之后,调用token工具类生成token返回客户端
     *
     * @param user  用户信息
     * @return 返回的信息
     */
    @Autowired
    private UserService userService;
    @PostMapping("/login")
    public Map<String, String> login(@RequestBody User user) {
        User userDb = userService.login(user);
        if (userDb == null) {
            throw new RuntimeException("用户不存在");
        }
        //用户校验成功
        HashMap<String, String> map = new HashMap<>();
        map.put("userName", userDb.getName());
        String token = jwtUtil.getToken(map);
        HashMap<String, String> resultMap = new HashMap<>();
        resultMap.put("state", "认证成功");
        resultMap.put("token", token);
        return resultMap;
    }
    /**
     * 单独对token进行解析校验测试,方式为post,token为参数传递,所以token要放在请求体中
     * 请求时候带着token,对token进行解析,正确返回成功信息,不成功,抛出对应的异常
     * @param token   token令牌信息
     * @return          验证的信息
     */
    @PostMapping("/verify")
    public Map<String,Object> verify(String token) {
        HashMap<String, Object> map = new HashMap<>();
        try {
            //调用token解析的工具类进行解析,没有异常说明校验成功
            DecodedJWT verifyToken = jwtUtil.verifyToken(token);
            //解析成功,返回成功的信息
            map.put("state", true);
            map.put("msg", "认证成功!");
            return map;
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msp", "签名不一致异常");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg", "令牌过期异常");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg", "算法不匹配异常");
        } catch (InvalidClaimException e) {
            e.printStackTrace();
            map.put("msg", "失效的payload异常");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效");
        }
        map.put("state", false);
        return map;
    }

    /**
     * 拦截器拦截校验token 校验成功然后放行执行业务代码
     * @param user
     * @return
     */
    @GetMapping("/interceptorVerify")
    public String jwtInterceptorVerify(@RequestBody User user) {
        //拦截器会拦截所有请求,此处进行正常的业务逻辑即可
        //查询用户名是否存在
        User userDb = userService.login(user);
        if (userDb == null) {
            return "用户不存在";
        }
        return "用户存在";
    }
}

测试类中对jwt的使用测试

public class JwtTokenTest {
    /**
     * 令牌的获取
     * 测试生成jwt的token令牌三部分组成
     * header(加密算法,类型) . payload(负载,可以不重要可以用得到的用户信息) . signature(签名,前两部跟base64加密和自己的秘钥)
     */
    @Test
    public void jwtToken() {
        HashMap<String, Object> map = new HashMap<>();//header中需要传递的map,无内容时使用jwt默认值
        //设置一个时间,作为令牌的过期时间 ,设置过期时间为60秒
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, 60);

        String token = JWT.create().withHeader(map)//header中已经有默认的算法和类型
                .withClaim("userId", 123456) //payload负载    工具类中通过map传递进行设置
                .withClaim("userName", "zhangsan") //payload可以传递多个
                .withExpiresAt(calendar.getTime())  //令牌不是无限期的,设置令牌的过期时间
                .sign(Algorithm.HMAC256("miyao"));//签名设计加密算法,还有设置自己的秘钥

        System.out.println(token);
    }

    /**
     * 解析token,注意有效期内
     */
    @Test
    public void verifyTest() {
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("miyao")).build();
        //进行token解析校验,参数为上方产生的token,注意有效期内
        DecodedJWT verify = jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6InpoYW5nc2FuIiwiZXhwIjoxNjIyMTIwNzgzLCJ1c2VySWQiOjEyMzQ1Nn0.wCobBUz5oRVmeaTBT5Omo_Ab3iTid8JrXRfqmxC-wqs");
        //解析完成之后可以获取payload负载中自包含放置的信息
        System.out.println(verify.getClaims());
        System.out.println(verify.getClaim("userId").asInt());
        System.out.println(verify.getClaim("userName").asString());
        //获取过期时间
        System.out.println(verify.getExpiresAt());

    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值