如何确保用户真实登陆?超时重新登陆?JWT来了。
JWT(Json Web Token),是一种工具,格式为XXXX.XXXX.XXXX的字符串,JWT以一种安全的方式在用户和服务器之间传递存放在JWT中的不敏感信息。
设想这样一个场景,在我们登录一个网站之后,再把网页或者浏览器关闭,下一次打开网页的时候可能显示的还是登录的状态,不需要再次进行登录操作,通过JWT就可以实现这样一个用户认证的功能。当然使用Session可以实现这个功能,但是使用Session的同时也会增加服务器的存储压力,而JWT是将存储的压力分布到各个客户端机器上,从而减轻服务器的压力。
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
这个类声明了一个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);
}
}
/**
* 拦截器
* @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;
}
}
/**
* 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();
}
}
/**
* 登陆
* @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 "登陆成功";
}
}
完成了,是不是比较简单!
https://github.com/zhouzhaodong/springboot/tree/master/springboot-jwt
http://www.zhouzhaodong.xyz