add
This commit is contained in:
@ -21,7 +21,8 @@ public class SecurityConstant {
|
|||||||
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
|
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
|
||||||
public static final String USER_DETAILS_REDIS_KEY = "user_details:";
|
public static final String USER_DETAILS_REDIS_KEY = "user_details:";
|
||||||
public static final String ONLINE_USER_REDIS_KEY = "online_user:";
|
public static final String ONLINE_USER_REDIS_KEY = "online_user:";
|
||||||
public static final String LOGGED_USER_REDIS_KEY = "logged_user:";
|
public static final String LAST_LOGIN_USER_REDIS_KEY = "last_login_user:";
|
||||||
|
public static final String LOGIN_USER_DEVICES_REDIS_KEY = "login_user_devices:";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,11 +26,6 @@ public class SecurityUser implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String userId;
|
private String userId;
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备SN
|
|
||||||
*/
|
|
||||||
private String deviceSn;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 部门ID
|
* 部门ID
|
||||||
*/
|
*/
|
||||||
|
@ -20,11 +20,4 @@ public interface SysUserDetailsApiService {
|
|||||||
*/
|
*/
|
||||||
UserDetails toCache(String username, String deviceSn);
|
UserDetails toCache(String username, String deviceSn);
|
||||||
|
|
||||||
/**
|
|
||||||
* 从缓存中删除
|
|
||||||
*
|
|
||||||
* @param username username
|
|
||||||
* @param deviceSn deviceSn
|
|
||||||
*/
|
|
||||||
void deleteCache(String username, String deviceSn);
|
|
||||||
}
|
}
|
||||||
|
@ -60,9 +60,15 @@ public class OnlineUserFilter extends OncePerRequestFilter {
|
|||||||
String deviceSn = onlineUserDto.getDeviceSn();
|
String deviceSn = onlineUserDto.getDeviceSn();
|
||||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
|
||||||
|
if (Objects.isNull(userDetails)) {
|
||||||
|
onlineUserService.deleteOne(username, deviceSn, true);
|
||||||
|
ResponseUtil.errorAuth(response, 4011, "登陆过期");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 不允许同时在线
|
// 不允许同时在线
|
||||||
if (!authConfigApiService.checkAllowBothOnline()) {
|
if (!authConfigApiService.checkAllowBothOnline()) {
|
||||||
if (redisService.hasKey(SecurityConstant.LOGGED_USER_REDIS_KEY + username)) {
|
if (redisService.hasKey(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username)) {
|
||||||
if (!onlineUserService.checkIsLastLogged(username, deviceSn)) {
|
if (!onlineUserService.checkIsLastLogged(username, deviceSn)) {
|
||||||
onlineUserService.deleteOne(username, deviceSn, true);
|
onlineUserService.deleteOne(username, deviceSn, true);
|
||||||
ResponseUtil.errorAuth(response, 4012, "被挤下线");
|
ResponseUtil.errorAuth(response, 4012, "被挤下线");
|
||||||
@ -72,13 +78,7 @@ public class OnlineUserFilter extends OncePerRequestFilter {
|
|||||||
ResponseUtil.errorAuth(response, 4011, "登陆过期");
|
ResponseUtil.errorAuth(response, 4011, "登陆过期");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 允许同时在线
|
|
||||||
else {
|
|
||||||
if (Objects.isNull(userDetails)) {
|
|
||||||
ResponseUtil.errorAuth(response, 4011, "登陆过期");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
|
@ -2,10 +2,10 @@ package com.qiaoba.auth.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
|
|
||||||
import com.qiaoba.api.auth.constants.SecurityConstant;
|
import com.qiaoba.api.auth.constants.SecurityConstant;
|
||||||
import com.qiaoba.api.auth.entity.OnlineUser;
|
import com.qiaoba.api.auth.entity.OnlineUser;
|
||||||
import com.qiaoba.api.auth.entity.dto.OnlineUserDto;
|
import com.qiaoba.api.auth.entity.dto.OnlineUserDto;
|
||||||
|
import com.qiaoba.api.auth.service.AuthConfigApiService;
|
||||||
import com.qiaoba.api.auth.service.OnlineUserService;
|
import com.qiaoba.api.auth.service.OnlineUserService;
|
||||||
import com.qiaoba.api.auth.utils.TokenUtil;
|
import com.qiaoba.api.auth.utils.TokenUtil;
|
||||||
import com.qiaoba.common.base.constants.BaseConstant;
|
import com.qiaoba.common.base.constants.BaseConstant;
|
||||||
@ -32,9 +32,8 @@ import java.util.List;
|
|||||||
public class OnlineUserServiceImpl implements OnlineUserService {
|
public class OnlineUserServiceImpl implements OnlineUserService {
|
||||||
|
|
||||||
private final RedisService redisService;
|
private final RedisService redisService;
|
||||||
private final SysUserDetailsApiService sysUserDetailsApiService;
|
|
||||||
private final HttpServletRequest request;
|
private final HttpServletRequest request;
|
||||||
|
private final AuthConfigApiService authConfigApiService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void insert(OnlineUser onlineUser) {
|
public void insert(OnlineUser onlineUser) {
|
||||||
@ -48,11 +47,31 @@ public class OnlineUserServiceImpl implements OnlineUserService {
|
|||||||
throw new ServiceException("禁止踢出自己!");
|
throw new ServiceException("禁止踢出自己!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deviceSn.equals(redisService.get(SecurityConstant.LOGGED_USER_REDIS_KEY + username))) {
|
// 删除在线用户信息
|
||||||
redisService.del(SecurityConstant.LOGGED_USER_REDIS_KEY + username);
|
|
||||||
}
|
|
||||||
sysUserDetailsApiService.deleteCache(username, deviceSn);
|
|
||||||
redisService.del(handleKey(username, deviceSn));
|
redisService.del(handleKey(username, deviceSn));
|
||||||
|
|
||||||
|
// 允许同时在线
|
||||||
|
if (authConfigApiService.checkAllowBothOnline()) {
|
||||||
|
// > 1 说明还有其他设备登录着 不能删除 userDetail || == 1 说明没有其他设备 可以删除 userDetail
|
||||||
|
if (redisService.hSize(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username) <= 1) {
|
||||||
|
// 删除 userDetail
|
||||||
|
redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 不允许同时在线
|
||||||
|
else {
|
||||||
|
// 最后登录的设备是自己 可以删除 userDetail
|
||||||
|
if (checkIsLastLogged(username, deviceSn)) {
|
||||||
|
redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除最后登录的用户设备
|
||||||
|
if (deviceSn.equals(redisService.get(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username))) {
|
||||||
|
redisService.del(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username);
|
||||||
|
}
|
||||||
|
// 删除 hash中的自己
|
||||||
|
redisService.hDel(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username, deviceSn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -82,7 +101,7 @@ public class OnlineUserServiceImpl implements OnlineUserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean checkIsLastLogged(String username, String deviceSn) {
|
public Boolean checkIsLastLogged(String username, String deviceSn) {
|
||||||
String loggedDevice = redisService.get(SecurityConstant.LOGGED_USER_REDIS_KEY + username).toString();
|
String loggedDevice = redisService.get(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username).toString();
|
||||||
return deviceSn.equals(loggedDevice);
|
return deviceSn.equals(loggedDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,14 @@ public interface RedisService {
|
|||||||
*/
|
*/
|
||||||
Map<Object, Object> hGetAll(String key);
|
Map<Object, Object> hGetAll(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取整个hash结构的大小
|
||||||
|
*
|
||||||
|
* @param key key
|
||||||
|
* @return size
|
||||||
|
*/
|
||||||
|
Long hSize(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 直接设置整个Hash结构
|
* 直接设置整个Hash结构
|
||||||
*
|
*
|
||||||
|
@ -102,6 +102,11 @@ public class RedisServiceImpl implements RedisService {
|
|||||||
return redisTemplate.opsForHash().entries(addTenantPrefix(key));
|
return redisTemplate.opsForHash().entries(addTenantPrefix(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long hSize(String key) {
|
||||||
|
return redisTemplate.opsForHash().size(addTenantPrefix(key));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean hSetAll(String key, Map<String, Object> map, long time) {
|
public Boolean hSetAll(String key, Map<String, Object> map, long time) {
|
||||||
String newKey = addTenantPrefix(key);
|
String newKey = addTenantPrefix(key);
|
||||||
|
@ -166,12 +166,13 @@ public class SysLoginServiceImpl implements SysLoginService {
|
|||||||
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
|
||||||
String browser = userAgent.getBrowser().getName() + BaseConstant.LINE_JOIN_STR + userAgent.getVersion();
|
String browser = userAgent.getBrowser().getName() + BaseConstant.LINE_JOIN_STR + userAgent.getVersion();
|
||||||
String os = userAgent.getOs().getName();
|
String os = userAgent.getOs().getName();
|
||||||
|
|
||||||
if (!authConfigApiService.checkAllowBothOnline()) {
|
|
||||||
redisService.set(SecurityConstant.LOGGED_USER_REDIS_KEY + username, deviceSn, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600);
|
|
||||||
}
|
|
||||||
OnlineUser onlineUser = new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date());
|
OnlineUser onlineUser = new OnlineUser(deviceSn, username, nickname, ip, address, browser, os, new Date());
|
||||||
onlineUserService.insert(onlineUser);
|
onlineUserService.insert(onlineUser);
|
||||||
|
redisService.set(SecurityConstant.LAST_LOGIN_USER_REDIS_KEY + username, deviceSn, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600);
|
||||||
|
// 允许同时在线
|
||||||
|
if (authConfigApiService.checkAllowBothOnline()) {
|
||||||
|
redisService.hSet(SecurityConstant.LOGIN_USER_DEVICES_REDIS_KEY + username, deviceSn, 1, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600);
|
||||||
|
}
|
||||||
return onlineUser;
|
return onlineUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.qiaoba.module.system.service.impl;
|
package com.qiaoba.module.system.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.qiaoba.api.auth.service.AuthConfigApiService;
|
||||||
|
import com.qiaoba.api.auth.service.OnlineUserService;
|
||||||
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
|
import com.qiaoba.api.auth.service.SysUserDetailsApiService;
|
||||||
import com.qiaoba.api.system.entity.SysUser;
|
import com.qiaoba.api.system.entity.SysUser;
|
||||||
import com.qiaoba.api.auth.constants.SecurityConstant;
|
import com.qiaoba.api.auth.constants.SecurityConstant;
|
||||||
@ -59,16 +61,8 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet
|
|||||||
SysUser user = sysUserService.selectByUsername(username);
|
SysUser user = sysUserService.selectByUsername(username);
|
||||||
UserDetails details = createUserDetails(user);
|
UserDetails details = createUserDetails(user);
|
||||||
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
|
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
|
||||||
securityUser.setDeviceSn(deviceSn);
|
|
||||||
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600);
|
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.TOKEN_EXPIRE_HOUR_TIME * 3600);
|
||||||
return details;
|
return details;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteCache(String username, String deviceSn) {
|
|
||||||
SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
|
|
||||||
if (Objects.nonNull(user) && deviceSn.equals(user.getDeviceSn())) {
|
|
||||||
redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user