如何确保用户真实登陆?超时重新登陆?JWT来了。
什么是JWT
JWT(Json Web Token),是一种工具,格式为XXXX.XXXX.XXXX的字符串,JWT以一种安全的方式在用户和服务器之间传递存放在JWT中的不敏感信息。
为什么要用JWT
设想这样一个场景,在我们登录一个网站之后,再把网页或者浏览器关闭,下一次打开网页的时候可能显示的还是登录的状态,不需要再次进行登录操作,通过JWT就可以实现这样一个用户认证的功能。当然使用Session可以实现这个功能,但是使用Session的同时也会增加服务器的存储压力,而JWT是将存储的压力分布到各个客户端机器上,从而减轻服务器的压力。
JWT操作流程图
Spring Boot整合
1. pom.xml配置依赖
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version></dependency>
2. 添加过滤器
这个类声明了一个JWT过滤器类,从Http请求中提取JWT的信息,并使用了secretkey这个密匙对JWT进行验证。
/** * 拦截器验证类 * @author zhouzhaodong */public class JwtFilter extends GenericFilterBean { /** * 秘钥 */ public static final String SECRET_KEY = "secretkey"; @Override public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) req; final HttpServletResponse response = (HttpServletResponse) res; // 从request中获取authorization final String authHeader = request.getHeader("authorization"); // 如果Http请求是OPTIONS,那么只需返回状态代码200即可。 String options = "OPTIONS"; if (options.equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { // 判断token是否是用Bearer 开头的 String header = "Bearer "; if (authHeader == null || !authHeader.startsWith(header)) { throw new ServletException("Missing or invalid Authorization header"); } // 然后从授权处获取JWT令牌 final String token = authHeader.substring(7); try { // 使用JWT解析器检查签名是否与Key "secretkey "有效。 final Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); // 在请求标题中添加claims request.setAttribute("claims", claims); } catch (final SignatureException e) { throw new ServletException("Invalid token"); } } chain.doFilter(req, res); }}
3. 拦截器
/** * 拦截器 * @author zhouzhaodong */@Configurationpublic class JwtCfg { @Bean public FilterRegistrationBean<JwtFilter> jwtFilter() { final FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new JwtFilter()); // 对/test/*下的url进行拦截验证 registrationBean.addUrlPatterns("/test/*"); return registrationBean; }}
4. 写一个JWT生成的方法类
/** * JWT生成类 * @author zhouzhaodong */public class JwtUtils { public static final String SUBJECT = "admin"; /** * 过期时间,毫秒,一天 */ public static final long EXPIRE = 1000 * 60 * 60 * 24; /** * 秘钥 */ public static final String SECRET_KEY = "secretkey"; /** * 生成jwt * @param userName * @param passWord * @return */ public static String geneJsonWebToken(String userName, String passWord) { if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) { return "用户名或密码不能为空"; } return Jwts.builder().setSubject(SUBJECT) .claim("userName", userName) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact(); }}
5. 写测试方法
/** * 登陆 * @author zhouzhaodong */@RestControllerpublic class TestController { @RequestMapping("/login") public String login(HttpServletResponse response, String userName, String passWord) { // 假装判断一下登陆是否成功 if(userName == null || "".equals(userName) || passWord == null || "".equals(passWord)){ return "用户名或者密码不能为空"; } String token = JwtUtils.geneJsonWebToken(userName, passWord); // 将token放在响应头 response.setHeader("Authorization", token); return token; } @RequestMapping("/secure/check") public String check(){ return "登陆成功"; }}
6. 启动验证
1. 运行IDEA
2. 使用postman进行测试
首先需要访问login获取token:
然后拿着该token去登录:
完成了,是不是比较简单!
源码地址
https://github.com/zhouzhaodo...
个人网站链接
http://www.zhouzhaodong.xyz