使用JWT进行用户认证和授权,而Session在一定程度上起到了辅助作用。让我们详细讨论JWT和Session在这种结合模式中的各自作用以及为什么需要Session。
JWT的作用
-
用户认证: JWT包含了用户的身份信息和权限信息,客户端每次请求时将JWT发送给服务器,服务器通过验证JWT来确认用户身份。 -
无状态性: JWT不需要在服务器端存储用户会话信息,因此服务器可以是无状态的,便于扩展和负载均衡。
Session的作用
-
附加的安全层: 即使JWT是无状态的,但在某些应用场景中,仅依赖JWT可能存在一些安全问题,例如Token的泄露或滥用。Session可以作为一个额外的安全层,确保Token即使有效,也必须在服务器的Session管理器中存在对应的会话。 -
管理Token的生命周期: 通过Session,可以更方便地管理Token的生命周期,例如强制用户重新登录、手动注销Token等操作。 -
控制“记住我”功能: 如果用户选择了“记住我”选项,Session可以记录这个状态,并在JWT过期后,通过Session来决定是否允许继续使用旧的Token。
为什么需要创建Session
尽管JWT可以在无状态环境中使用,但Session的引入带来了以下好处:
-
防止Token滥用: 通过在服务器端验证Session,可以确保即使Token有效,也必须是经过服务器端认证的,从而防止Token被恶意使用。 -
支持用户主动注销: 当用户选择注销时,可以直接删除服务器端的Session记录,确保Token即使没有过期,也无法再被使用。 -
提供更精细的控制: 通过Session,可以实现更精细的权限控制和用户状态管理,例如强制下线、会话过期时间控制等。 -
状态追踪: 在某些场景下,追踪用户状态是必要的,例如监控用户的活跃度、登录历史等,这些信息可以通过Session进行管理。
结合JWT和Session的优势
结合使用JWT和Session,可以同时利用两者的优点,实现安全性和扩展性的平衡:
-
无状态认证: JWT可以实现无状态认证,便于系统的水平扩展和负载均衡。 -
状态管理和安全性: Session可以提供额外的状态管理和安全性,确保Token的使用更加安全可靠。
代码示例
以下是一个简化的代码示例,展示了如何在用户登录时创建JWT和Session:
public LoginResponse login(String username, String password) throws AuthException {
// 验证用户名和密码
User user = userService.authenticate(username, password);
if (user == null) {
throw new AuthException("Invalid username or password");
}
// 生成JWT Token
String token = createJwt(user.getId(), user.getRoles());
// 创建会话
sessionManagerApi.createSession(token, user);
// 返回Token
return new LoginResponse(token);
}
public void createSession(String token, User user) {
LoginUser loginUser = new LoginUser();
loginUser.setToken(token);
loginUser.setUserId(user.getId());
loginUser.setRoles(user.getRoles());
sessionManagerApi.saveSession(token, loginUser);
}
在请求验证时,首先验证JWT的有效性,然后检查Session中是否存在对应的会话:
@Override
public DefaultJwtPayload validateToken(String token) throws AuthException {
try {
// 1. 先校验jwt token本身是否有问题
JwtContext.me().validateTokenWithException(token);
// 2. 获取jwt的payload
DefaultJwtPayload defaultPayload = JwtContext.me().getDefaultPayload(token);
// 3. 如果是7天免登陆,则不校验session过期
if (defaultPayload.getRememberMe()) {
return defaultPayload;
}
// 4. 判断session里是否有这个token
LoginUser session = sessionManagerApi.getSession(token);
if (session == null) {
throw new AuthException(AUTH_EXPIRED_ERROR);
}
return defaultPayload;
} catch (JwtException jwtException) {
if (JwtExceptionEnum.JWT_EXPIRED_ERROR.getErrorCode().equals(jwtException.getErrorCode())) {
throw new AuthException(AUTH_EXPIRED_ERROR);
} else {
throw new AuthException(TOKEN_PARSE_ERROR);
}
} catch (io.jsonwebtoken.JwtException jwtSelfException) {
throw new AuthException(TOKEN_PARSE_ERROR);
}
}
总结
在这个场景中,JWT用于无状态的用户认证,提供便捷和扩展性;Session作为辅助,提供额外的安全性和状态管理。通过这种结合,可以充分利用两者的优点,确保系统既具备高扩展性,又能提供细致的安全控制。
作者:云原生melo荣 来源:juejin.cn/post/7383017171180568630
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持我们,共同成长
原文始发于微信公众号(Java知音):token是用来鉴权的,那session是用来干什么的?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/301038.html