今天在处理这个功能时本能地想到,好像在配置文件中有印象过通过配置用户数量就可以实现 限制用户功能。但是找了半天没找到 ,后来想到 那是采用session时的一个maxSession参数,分离版使用JWT没有用到session也就没了。
后来我就好奇为什么JWT没有类似的参数配置...(其实是因为我懒,不想写哈哈哈)
那就实现一个吧,思路很简单,由于JWT的无状态特性,用户信息(token)都存在redis中,我们可以拿到redis中的在线用户数量,再与我们的系统最大限制数进行比对就可以了,达到最大就拦截请求。
限制登陆拦截器
/**
* 最大用户登录数限制
*
* @author jiangfy
*/
@Component
public class MaxOnlineUsersInterceptor implements HandlerInterceptor {
// 最大在线用户数量
private int maxOnlineUsers;
@Resource
private RedisCache redisCache;
@Resource
private ISysUserOnlineService userOnlineService;
@Resource
ISysConfigService configService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//我这边是把最大用户数量的配置放在了若依自带的sys_config配置表中,你也可以自定义在配置文件中都可以。
maxOnlineUsers = Integer.parseInt(configService.selectConfigByKey("sys.user.loginNum"));
// 检查当前在线用户数量是否已经达到最大限制
Long loginUserNum = getLoginUserNum();
if (loginUserNum >= maxOnlineUsers) {
// 当前在线用户数量超过最大限制
Map<String, Object> responseData = new HashMap<>();
// 这边是因为有特定的返回格式所以处理下
responseData.put("code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
responseData.put("msg", "当前系统用户数量过多,请稍后再试!");
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(responseData);
//这里是请求响应状态status,跟响应结果code不一样
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
return false;
}
return true;
}
// 获取当前在线用户数量
private Long getLoginUserNum() {
Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys) {
LoginUser user = redisCache.getCacheObject(key);
user.setExpireTime(redisCache.getKeyExpire(key));
userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
}
Collections.reverse(userOnlineList);
userOnlineList.removeAll(Collections.singleton(null));
long total = new PageInfo(userOnlineList).getTotal();
return total;
}
}
注册拦截器
/**
* @Author Jiangfy
* @Description 防止超过系统最大登陆人数拦截器
**/
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
private MaxOnlineUsersInterceptor maxOnlineUsersInterceptor;
/**
* 添加过滤器
*
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//这里只对登录方法进行拦截其余不处理
registry.addInterceptor(maxOnlineUsersInterceptor).addPathPatterns("/login");
}
}
最近写拦截器太多,感觉什么都能用拦截器处理啧啧
就这样吧,还挺好用