老系统,记录一个 session 使用问题导致的鉴权问题
维护一个老系统,发现因后端拦截器 session 使用不当,导致用户退出登录后鉴权信息未被清除,引起后续接口鉴权问题。属于一个很容易疏忽的问题,以作记录
问题描述
端 session 使用不当,导致用户退出登录后鉴权信息未被清除,引起后续接口鉴权问题
伪代码复现
在系统统一的请求拦截器通过读取请求 header 中的 token 鉴权信息,解析出用户角色信息放在 session 中方便后续读取
伪代码如下:
复制
展开
public class Test implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (StrTool.isNotBlank(token)) {
request.getSession().setAttribute("Token", token);
request.getSession().setAttribute("User", UserTool.getUserFromToken(token));
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
解决方式
我们都知道 session 缓存是一次会话中的缓存,也就意味着如果页面没有刷新、sessionId 没有更改,退出登录后 session 缓存中的 User 信息没有被清除
而后续的自定义接口鉴权注解是通过读取 session 中的 User session 缓存作鉴权,从而导致越权问题
由于前端在退出登陆时只是清除了一下用户信息、token 信息,在不做很多变更的前提下,只能在后端的拦截器中二次判断一下 token 不存在就主动删除当前 session 缓存中的 User 信息
复制
展开
public class Test implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Authorization");
if (StrTool.isNotBlank(token)) {
request.getSession().setAttribute("Token", token);
request.getSession().setAttribute("User", UserTool.getUserFromToken(token));
} else {
// 原有代码未作主动删除,这里每次都校验并清除一下 session 缓存
request.getSession().removeAttribute("Token");
request.getSession().removeAttribute("User");
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
其实可以利用 ThreadLocal 做一个 UserHolder 也可以更好地控制这些问题,比如:
复制
展开
public class UserHolder {
private static final ThreadLocal<User> userThreadLocal = new ThreadLocal<>();
public static void setUser(User user) {
userThreadLocal.set(user);
}
public static User getUser() {
return userThreadLocal.get();
}
public static void clear() {
userThreadLocal.remove();
}
}
作者:https://blog.xn--rpv331d.com/望舒
链接:https://blog.xn--rpv331d.com/望舒/blog/129
转载请保留文章出处...
No data
