【SpringBoot】拦截器处理JWT验证
发布日期:2021-06-29 21:37:46 浏览次数:2 分类:技术文章

本文共 6357 字,大约阅读时间需要 21 分钟。

在上文中,我们已经了解到了JWT并进行了实现,但是在每个接口都进行验证会使得代码非常冗余,因此本文中,我们将结合SpringBoot2.x进行整合,将JWT验证放到拦截器中进行实现。

JWT认证流程图如下:

在这里插入图片描述

创建包结构:

在这里插入图片描述
Maven依赖信息:

com.auth0
java-jwt
3.11.0
com.alibaba
fastjson
1.2.28
io.jsonwebtoken
jjwt
0.9.0

TestController 代码:

package com.dl.jwt.controller;import com.auth0.jwt.interfaces.DecodedJWT;import com.dl.jwt.utils.JavaJWTUtil;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest;import java.util.HashMap;import java.util.Map;@Controller@RequestMapping("/manage/")@Slf4jpublic class TestController {
@ResponseBody @RequestMapping(value = "login.do",method = RequestMethod.GET) public Map
login(String userid,String password){
/** *验证逻辑为了简便这里就不去做了 **/ //后端数据库校验成功 Map
payload=new HashMap<>(); payload.put("username","dingli"); payload.put("userid",userid); String token= JavaJWTUtil.getToken(payload,30); Map
map=new HashMap<>(); map.put("state",true); map.put("msg","认证成功!"); map.put("token",token); log.info("认证token为:{}",token); return map; } @ResponseBody @RequestMapping(value = "test.do",method = RequestMethod.POST) public Map
test(HttpServletRequest request){
Map
map=new HashMap<>(); String token=request.getHeader("token");//缓存在客户端,只要没过期,即使服务端重启也可以认证成功 DecodedJWT verify=JavaJWTUtil.verify(token); System.out.println("用户id:"+verify.getClaim("userid").asString()); map.put("state",true); map.put("msg","请求成功!"); return map; }}

自定义JWT拦截器(JWTIntercepter )代码

package com.dl.jwt.intercepters;import com.alibaba.fastjson.JSONObject;import com.auth0.jwt.exceptions.AlgorithmMismatchException;import com.auth0.jwt.exceptions.InvalidClaimException;import com.auth0.jwt.exceptions.SignatureVerificationException;import com.auth0.jwt.exceptions.TokenExpiredException;import com.auth0.jwt.interfaces.DecodedJWT;import com.dl.jwt.utils.JavaJWTUtil;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.extern.slf4j.Slf4j;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;import java.util.Map;/** * 自定义拦截器验证token */@Slf4jpublic class JWTIntercepter implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map
map=new HashMap<>(); String token=request.getHeader("token");//获取请求头中的token log.info("当前token为:{}",token); try{
JavaJWTUtil.verify(token);//验证token return true;//验证通过,就会去controller请求数据了 }catch(SignatureVerificationException ex){
ex.printStackTrace(); map.put("msg","无效签名!"); }catch(TokenExpiredException ex){
ex.printStackTrace(); map.put("msg","token过期!"); }catch(AlgorithmMismatchException ex){
ex.printStackTrace(); map.put("msg","token算法不一致"); }catch(Exception ex){
ex.printStackTrace(); map.put("msg","token无效!"); } map.put("state",false); //String jsonObject =new ObjectMapper().writeValueAsString(map); //采用jackson //将map转为json采用 fastjackson String jsonObject= JSONObject.toJSONString(map); response.setContentType("application/json;charset=UTF-8"); response.getWriter().println(jsonObject);//错误信息发送回前台 return false; }}

创建实现WebMvcConfigurer接口的配置类把拦截器添加到拦截器链中,WebMvcConfig代码:

package com.dl.jwt.config;import com.dl.jwt.intercepters.JWTIntercepter;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class WebMvcConfig implements WebMvcConfigurer {
@Override public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTIntercepter()) .addPathPatterns("/manage/**") //拦截/manage请求下的所有请求 .excludePathPatterns("/manage/login.do"); //登录请求拦截 }}

JavaJwtUtil代码:

import com.auth0.jwt.JWT;import com.auth0.jwt.JWTCreator;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.interfaces.DecodedJWT;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import java.util.Calendar;import java.util.Map;public class JavaJWTUtil {
private static String secret="csdntonghuasdfni#2323!@seirninfsasdf";//这个secret我们一般写在配置文件或者存放常量的类中,这里为了方便直接写在这儿 /** * 生成token header.payload.signature * @param map :payload中需要存放的信息,以map方式传入 * @param day :过期时间,以秒为单位 * @return */ public static String getToken(Map
map,Integer day){
Calendar instance=Calendar.getInstance(); instance.add(Calendar.SECOND,day); //创建jwt builder JWTCreator.Builder builder=JWT.create(); //payload,这里采用lambda表达式设置 map.forEach((k,v)->{
builder.withClaim(k,v); }); String token=builder.withExpiresAt(instance.getTime())//指定令牌过期时间 .sign(Algorithm.HMAC256(secret)); return token; } /** * 验证token合法性,不合法会抛出异常信息 * @param token : 前端传来的token * @return */ public static DecodedJWT verify(String token){
//如果有任何验证异常,此处都会抛出异常,因此我们可以捕获这些异常来反馈信息回前端 DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(secret)).build().verify(token); return decodedJWT; }}

采用Postman进行接口测试

登录请求生成token接口示例:
在这里插入图片描述
验证token请求示例,/manage下的非登录请求,上面生成的token添加到请求头中
在这里插入图片描述

转载地址:https://dh-butterfly.blog.csdn.net/article/details/110003775 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Redis(三)发布订阅、主从复制、哨兵模式和集群
下一篇:一文读懂JWT+JAVA的两种实现方式

发表评论

最新留言

很好
[***.229.124.182]2024年04月29日 02时56分25秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章