现在可以说,JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。
它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。
在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。
缺点是无法作废已颁布的令牌/不易应对数据过期。
英文网址如下:https://jwt.io/introduction/
Token相对于Cookie/Session的
支持跨域访问: Cookie是不允许垮域访问的,token支持
无状态: token无状态,session有状态的
去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在 你的API被调用的时候, 你可以进行Token生成调用即可.
更适用于移动应用: Cookie不支持手机端访问的
性能: 在网络传输的过程中,性能更好
基于标准化: 你的API可以采用标准化的 JSON Web Token (JWT).
token的用法思路很简单,这也是它很棒的一点。
用户登陆的时候,我们生成一个token,放在返回里给到登陆用户。
用户查询其他资源的请求过来时,带着token一起过来,然后我们再验证token。
首先在pom.xml里引入java-jwt
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.0</version>
</dependency>
然后我们写一个工具类JwtUtils, 里面写生成token的代码逻辑。
public static String createToken(Long ttlMillis, String username) {
// ttlMillis = MoreObjects.firstNonNull(ttlMillis, EXPIRE_TIME);
Long time = ( ttlMillis != null || ttlMillis.longValue() != 0)? ttlMillis: EXPIRE_TIME;
Date date = new Date(System.currentTimeMillis() + time);
Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
return JWT.create()
.withClaim("username", username) // 附带 username 信息
.withExpiresAt(date) // 到期时间
.sign(algorithm); // 创建一个新的 JWT,并使用给定的算法进行标记
}
主要逻辑时JWT.create()这个方法,这个方法的具体含义可以参考这篇文章。
https://blog.csdn.net/y368769/article/details/105675565jwt源码解析
这个方法写好,用户登陆的时候做完登陆验证,再调用下这个方法拿到token给出去就好了。
String userName = birth.getString("userName");
String password = birth.getString("password");
String token = null;
if(userService.login(userName, password)) {
//request.getSession().setAttribute("userName", userName); 请求里加上session,表明登陆状态
try {
token = JwtUtil.createToken(userName);//生成token
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
验证token的逻辑是在拦截器里处理。
首先定义一个验证token的拦截器。他是继承了默认拦截器HandlerInterceptor
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token = request.getHeader("access_token");
if (null != token) {
//验证token是否正确
boolean result = JwtUtil.verify(token);
if (result) {
return true;
}
}
response.sendError(401,"没有token,不能访问系统,请先登录");
return false;
}
在springmvc.xml配置文件里增加如下配置
<!-- 拦截器,拦截请求,检查token -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login"/>
<bean class="com.xxx.xxx.TokenInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
这样就完成了。
参考文章:
https://www.cnblogs.com/moyand/p/9047978.html