SpringBoot + JWT实现Token验证


需求

  • SpringBoot项目集成JWT,实现Token验证,保存用户登录状态。
  • 项目已上传到github,欢迎参考~
    • https://github.com/ABCVBNM/jwt_demo.git

实现

1. 添加依赖

这里选择的是jwtk/jjwt(因为看github上的Java_JWT项目,该项目维护最及时,星星最多)

	<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-api</artifactId>
        <version>0.11.2</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-impl</artifactId>
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
        <version>0.11.2</version>
        <scope>runtime</scope>
    </dependency>
    <!-- Uncomment this next dependency if you are using JDK 10 or earlier and you also want to use
         RSASSA-PSS (PS256, PS384, PS512) algorithms.  JDK 11 or later does not require it for those algorithms:-->
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.60</version>
        <scope>runtime</scope>
    </dependency>`
2. 编写编写TokenUtils类
1. 添加生成Token方法getToken
2. 添加解析Token方法parseToken
3. 添加验证Token方法verifyToken

因为要适配的项目业务不多,所以将用户信息保存在静态变量中,实现缓存的效果,每次解析Token都会进行对比。

	      public String getToken(User user) {

		        // String jws = Jwts.builder().setSubject(user.getUserName()).setExpiration(new Date(System.currentTimeMillis() + 3600 * 24 * 1000)).signWith(key).compact();
		        user.setPassWord("");
				// user.setUserName("");
		        Claims claims = Jwts.claims();
		        claims.put("user", user);
		        userName = user.getUserName();
		        admin = user.getAdmin();
		        warehouseName = user.getWarehouseName();
		        String jws = Jwts.builder().setClaims(claims).setExpiration(new Date(System.currentTimeMillis() + 3600 * 24 * 1000)).signWith(key).compact();
		        return jws;
		    }
		
		    public HashMap parseToken(String token) {
		        try {
		            LinkedHashMap userMap = (LinkedHashMap) Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody().get("user");
		            return userMap;
		        } catch (ExpiredJwtException e) {
		            e.printStackTrace();
		        } catch (UnsupportedJwtException e) {
		            e.printStackTrace();
		        } catch (MalformedJwtException e) {
		            e.printStackTrace();
		        } catch (SignatureException e) {
		            e.printStackTrace();
		        } catch (IllegalArgumentException e) {
		            e.printStackTrace();
		        }
		        return null;
		    }
		
			// 拦截器用
		    public boolean verifyToken(String token) {
		        HashMap map = parseToken(token);
		        if (map == null) return false;
		        if (map.get("userName").equals(userName) || map.get("admin").equals(admin) || map.get("warehouseName").equals(warehouseName))
		            return true;
		        return false;
		    }  
3. 添加过滤器

拦截请求,调用Tokenutil进行token校验,校验失败返回401。
SpringBoot中编写过滤器,只需要实现HandlerInterceptor接口即可。

	@Component
	public class LoginHandlerInterceptor implements HandlerInterceptor {
	
	    @Resource(name = "tokenUtilService")
	    TokenUtilService tokenUtilService;
	
	    @Override
	    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
	        String token = request.getHeader("L_Token");
	        if (token == null || !tokenUtilService.verifyToken(token)) {
	            response.setStatus(401);
	            response.getWriter().print("无效的Token,请重新登录!");
	            response.getWriter().flush();
	            return false;
	        }
	        return true;
	    }
	
	//    todo: print logs
	    @Override
	    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
	
	    }
	
	    @Override
	    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
	
	    }
	}
4. 添加配置类,配置过滤器

excludePath中添加需要放行的请求,这里边只添加了login

	@Configuration
	public class LoginInterceptConf implements WebMvcConfigurer {
	
	    @Resource
	    LoginHandlerInterceptor loginHandlerInterceptor;
	
	    @Override
	    public void addInterceptors(InterceptorRegistry registry) {
	        registry.addInterceptor(loginHandlerInterceptor).excludePathPatterns("/login");
	    }
	}
5. 编写登陆类
1. 实现登录接口
2. 实现根据Token获取用户信息接口


	@Controller
	public class Login {
	    public static String userName = "li";
	    public static String passWord = "lei";
	    public static String admin = "1";
	
	    @Resource(name = "tokenUtilService")
	    TokenUtilService tokenUtilService;
	
	    @RequestMapping(method = RequestMethod.POST, value = "/login")
	    @ResponseBody
	    public String login(@RequestBody User user) {
	        Result result = new Result();
	        if (user.getUserName().equals(userName) && user.getPassWord().equals(passWord)) {
	            user.setAdmin(admin);
	            user.setWarehouseName("深圳实验室");
	            result.setMsg("success!");
	            result.setCode("200");
	            result.setToken(tokenUtilService.getToken(user));
	        } else {
	            result.setMsg("fail");
	            result.setCode("404");
	        }
	        return JSON.toJSONString(result);
	    }
	
	    @RequestMapping(method = RequestMethod.POST, value = "/getUserInfo")
	    @ResponseBody
	    public HashMap getUserInfoByToken(String token) {
	        HashMap map = tokenUtilService.parseToken(token);
	        return map;
	    }
	
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值