diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/constants/SecurityConstant.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/constants/SecurityConstant.java index 44fab99..a1510e1 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/constants/SecurityConstant.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/constants/SecurityConstant.java @@ -15,6 +15,14 @@ import java.util.List; */ public class SecurityConstant { + /** + * 被挤下线 + */ + public static final int HTTP_SQUEEZED_OFFLINE = 4011; + + + + public static final int MAX_ERROR_COUNT = 5; public static final String LOGOUT_URL = "/logout"; public static final String HAS_BEEN_PULLED_BLACK = "您的IP已经被系统拉黑"; @@ -31,6 +39,7 @@ public class SecurityConstant { public static final String REDIS_SECRET_KEY = "sys:secret:secret"; public static final String USER_DETAILS_REDIS_KEY = "user_details:"; public static final String ONLINE_USER_REDIS_KEY = "online_user:"; + public static final String LOGGED_USER_REDIS_KEY = "logged_user:"; public static final String TOKEN_EXPIRE_TIME_KEY = ConfigConstant.SYS_CONFIG_KEY_PREFIX + "sys.token.expireTime"; /** * 登录成功 diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java index cbf750d..6e7c8a0 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/LoginUser.java @@ -23,6 +23,10 @@ public class LoginUser implements UserDetails { private static final long serialVersionUID = 1L; + /** + * 设备号 暂用UUID + */ + private String deviceSn; /** * 用户ID */ @@ -70,6 +74,14 @@ public class LoginUser implements UserDetails { this.roles = roles; } + public String getDeviceSn() { + return deviceSn; + } + + public void setDeviceSn(String deviceSn) { + this.deviceSn = deviceSn; + } + public List getRoles() { return roles; } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java index e3c7f6b..f5f8286 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/entity/OnlineUser.java @@ -17,6 +17,11 @@ public class OnlineUser implements Serializable { private static final long serialVersionUID = 1L; + /** + * 设备号 暂用UUID + */ + private String deviceSn; + /** * 登录账号 */ diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java index 58aa565..8d4fd22 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/JwtAuthenticationTokenFilter.java @@ -3,6 +3,7 @@ package com.qiaoba.auth.filters; import cn.hutool.core.util.StrUtil; import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.OnlineUser; +import com.qiaoba.auth.properties.AuthConfigProperties; import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.common.web.utils.ResponseUtil; @@ -34,26 +35,31 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { private final UserDetailsService userDetailsService; private final OnlineUserService onlineUserService; + private final AuthConfigProperties authConfigProperties; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + if (authConfigProperties.getWhitelist().contains(request.getRequestURI())) { + chain.doFilter(request, response); + return; + } + // 取Header中的Token String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER); if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) { String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length()); // todo - String username1 = "admin"; +/* String username1 = "admin"; OnlineUser onlineUser = onlineUserService.selectByUsername(username1); if (Objects.isNull(onlineUser)) { - // todo 返回401 - ResponseUtil.response(response, ""); + ResponseUtil.errorAuth(response, 4011, "暂无登录"); return; - } + }*/ // 续期有效期 - onlineUserService.insert(onlineUser); + //onlineUserService.insert(onlineUser); if (TokenUtil.validateToken(authToken)) { String username = TokenUtil.getUserNameFromToken(authToken); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/AccessDeniedHandler.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/AccessDeniedHandler.java index 55fd811..b590781 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/AccessDeniedHandler.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/AccessDeniedHandler.java @@ -1,9 +1,7 @@ package com.qiaoba.auth.handler; import cn.hutool.http.HttpStatus; -import cn.hutool.json.JSONUtil; import com.qiaoba.auth.constants.SecurityConstant; -import com.qiaoba.common.base.result.AjaxResult; import com.qiaoba.common.web.utils.ResponseUtil; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; @@ -25,7 +23,6 @@ import java.io.IOException; public class AccessDeniedHandler implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - AjaxResult result = AjaxResult.error(HttpStatus.HTTP_UNAUTHORIZED, SecurityConstant.ACCESS_DENIED); - ResponseUtil.response(response, JSONUtil.toJsonStr(result)); + ResponseUtil.errorAuth(response, HttpStatus.HTTP_UNAUTHORIZED, SecurityConstant.ACCESS_DENIED); } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java index e8716a3..465901b 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/handler/LogoutHandler.java @@ -1,6 +1,8 @@ package com.qiaoba.auth.handler; +import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.LoginUser; +import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.common.redis.service.RedisService; import lombok.RequiredArgsConstructor; import org.springframework.security.core.Authentication; @@ -24,11 +26,13 @@ import java.io.IOException; public class LogoutHandler implements LogoutSuccessHandler { private final RedisService redisService; + private final OnlineUserService onlineUserService; @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 删除缓存中的用户信息 LoginUser user = (LoginUser) authentication.getPrincipal(); - redisService.del(user.getUserId()); + redisService.del(SecurityConstant.USER_DETAILS_REDIS_KEY + user.getUsername()); + onlineUserService.deleteOne(user.getUsername(), user.getDeviceSn()); } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java index 55f2c0c..e88ea8a 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/OnlineUserService.java @@ -24,16 +24,25 @@ public interface OnlineUserService { * 删除(强退) * * @param username 登录账号 + * @param deviceSn 设备号 */ - void delete(String username); + void deleteOne(String username, String deviceSn); + + /** + * 删除(强退) + * + * @param username 登录账号 + */ + void deleteAll(String username); /** * 查询 * * @param username 登录账号 + * @param deviceSn deviceSn * @return 在线用户 */ - OnlineUser selectByUsername(String username); + OnlineUser selectOne(String username, String deviceSn); /** * 批量查询 @@ -42,4 +51,6 @@ public interface OnlineUserService { * @return list */ List selectList(String username); + + } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java index 8e6423a..79a4d4e 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/service/impl/OnlineUserServiceImpl.java @@ -27,18 +27,26 @@ public class OnlineUserServiceImpl implements OnlineUserService { @Override public void insert(OnlineUser onlineUser) { - redisService.set(handleKey(onlineUser.getUsername()), onlineUser, TokenUtil.expireTime * 3600); + // key: username + // hashKey: deviceSn + // value: onlineUser + redisService.hSet(handleKey(onlineUser.getUsername()), onlineUser.getDeviceSn(), onlineUser, TokenUtil.expireTime * 3600); } @Override - public void delete(String username) { + public void deleteOne(String username, String deviceSn) { + redisService.hDel(handleKey(username), deviceSn); + } + + @Override + public void deleteAll(String username) { redisService.del(handleKey(username)); } @Override - public OnlineUser selectByUsername(String username) { - if (redisService.hasKey(handleKey(username))) { - return redisService.getObject(handleKey(username), OnlineUser.class); + public OnlineUser selectOne(String username, String deviceSn) { + if (redisService.hHasKey(username, deviceSn)) { + return redisService.hGetObject(username, deviceSn, OnlineUser.class); } return null; } diff --git a/qiaoba-auth/src/main/resources/META-INF/spring.factories b/qiaoba-auth/src/main/resources/META-INF/spring.factories index 74fb571..7d860de 100644 --- a/qiaoba-auth/src/main/resources/META-INF/spring.factories +++ b/qiaoba-auth/src/main/resources/META-INF/spring.factories @@ -5,4 +5,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.qiaoba.auth.filters.JwtAuthenticationTokenFilter,\ com.qiaoba.auth.advice.SecurityExceptionAdvice,\ com.qiaoba.auth.aspectj.DataScopeAspect,\ + com.qiaoba.auth.service.impl.OnlineUserServiceImpl,\ com.qiaoba.auth.config.SpringSecurityConfig diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java index c573081..44a5f7e 100644 --- a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/RedisService.java @@ -354,4 +354,15 @@ public interface RedisService { * @return // List */ List getObjectList(String key, Class clazz); + + /** + * hGetObject + * + * @param key key + * @param hashKey hashKey + * @param clazz clazz + * @param T + * @return clazz + */ + T hGetObject(String key, String hashKey, Class clazz); } diff --git a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java index 39cbc74..017dd32 100644 --- a/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java +++ b/qiaoba-commons/qiaoba-common-redis/src/main/java/com/qiaoba/common/redis/service/impl/RedisServiceImpl.java @@ -229,6 +229,12 @@ public class RedisServiceImpl implements RedisService { return (List) get(key); } + @Override + @SuppressWarnings("unchecked") + public T hGetObject(String key, String hashKey, Class clazz) { + return (T) hGet(key, hashKey); + } + private String handleKey(String key) { StringBuilder sb = new StringBuilder(); sb.append("tenant_").append(BaseContext.getTenantId()).append(":").append(key); diff --git a/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/ResponseUtil.java b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/ResponseUtil.java index ba30a92..9518d34 100644 --- a/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/ResponseUtil.java +++ b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/ResponseUtil.java @@ -1,5 +1,8 @@ package com.qiaoba.common.web.utils; +import cn.hutool.json.JSONUtil; +import com.qiaoba.common.base.result.AjaxResult; + import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -18,4 +21,8 @@ public class ResponseUtil { response.getWriter().write(msg); } + public static void errorAuth(HttpServletResponse response, Integer code, String msg) throws IOException { + AjaxResult result = AjaxResult.error(code, msg); + response(response, JSONUtil.toJsonStr(result)); + } } diff --git a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java index d7a0780..0bd5b84 100644 --- a/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java +++ b/qiaoba-modules/qiaoba-module-system/src/main/java/com/qiaoba/module/system/service/impl/SysUserDetailsServiceImpl.java @@ -8,6 +8,7 @@ import com.qiaoba.auth.constants.SecurityConstant; import com.qiaoba.auth.entity.LoginUser; import com.qiaoba.auth.entity.SecurityUser; import com.qiaoba.auth.entity.dto.RoleDto; +import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.common.base.enums.BaseEnum; import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.module.system.service.SysMenuService; @@ -62,7 +63,7 @@ public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDet SysUser user = sysUserService.selectByUsername(username); UserDetails details = createUserDetails(user); SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class); - redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser); + redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser, TokenUtil.expireTime * 3600); return details; } }