共计 3202 个字符,预计需要花费 9 分钟才能阅读完成。
如何确保用户真实登陆?超时重新登陆?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
*/
@Configuration
public 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
*/
@RestController
public 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
正文完