From 96699e55c33d0c9c94950a403d8d27b008353084 Mon Sep 17 00:00:00 2001 From: ailanyin Date: Thu, 6 Jul 2023 16:16:51 +0800 Subject: [PATCH] add --- .../src/main/resources/application.yml | 1 + .../auth/config/SpringSecurityConfig.java | 8 +-- ...nCoreFilter.java => OnlineUserFilter.java} | 36 +++++------- .../filters/SecurityContextHolderFilter.java | 55 +++++++++++++++++++ .../qiaoba/auth/handler/LogoutHandler.java | 7 ++- .../main/resources/META-INF/spring.factories | 3 +- .../qiaoba/common/base/order/FilterOrder.java | 22 ++++++++ .../qiaoba/common/web/utils/ResponseUtil.java | 3 +- .../filters/DynamicDataSourceFilter.java | 3 +- 9 files changed, 106 insertions(+), 32 deletions(-) rename qiaoba-auth/src/main/java/com/qiaoba/auth/filters/{AuthenticationCoreFilter.java => OnlineUserFilter.java} (68%) create mode 100644 qiaoba-auth/src/main/java/com/qiaoba/auth/filters/SecurityContextHolderFilter.java create mode 100644 qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/order/FilterOrder.java diff --git a/qiaoba-application/src/main/resources/application.yml b/qiaoba-application/src/main/resources/application.yml index e454204..7ec2796 100644 --- a/qiaoba-application/src/main/resources/application.yml +++ b/qiaoba-application/src/main/resources/application.yml @@ -91,6 +91,7 @@ qiaoba: - /druid/** - /resource/** - /login + - /getInfo - /register - /captchaImage - /tenant/normal-list diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/config/SpringSecurityConfig.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/config/SpringSecurityConfig.java index a218085..5ab2d06 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/config/SpringSecurityConfig.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/config/SpringSecurityConfig.java @@ -1,7 +1,7 @@ package com.qiaoba.auth.config; import com.qiaoba.api.auth.constants.SecurityConstant; -import com.qiaoba.auth.filters.AuthenticationCoreFilter; +import com.qiaoba.auth.filters.SecurityContextHolderFilter; import com.qiaoba.auth.handler.AccessDeniedHandler; import com.qiaoba.auth.handler.LogoutHandler; import com.qiaoba.auth.properties.AuthConfigProperties; @@ -36,7 +36,7 @@ public class SpringSecurityConfig { private final AuthConfigProperties authConfigProperties; private final AccessDeniedHandler accessDeniedHandler; - private final AuthenticationCoreFilter authenticationCoreFilter; + private final SecurityContextHolderFilter securityContextHolderFilter; private final LogoutHandler logoutHandler; @@ -72,8 +72,8 @@ public class SpringSecurityConfig { // 退出处理 httpSecurity.logout().logoutUrl(SecurityConstant.LOGOUT_URI).logoutSuccessHandler(logoutHandler); // 添加JWT filter - httpSecurity.addFilterBefore(authenticationCoreFilter, UsernamePasswordAuthenticationFilter.class); - httpSecurity.addFilterBefore(authenticationCoreFilter, LogoutFilter.class); + httpSecurity.addFilterBefore(securityContextHolderFilter, UsernamePasswordAuthenticationFilter.class); + httpSecurity.addFilterBefore(securityContextHolderFilter, LogoutFilter.class); return httpSecurity.build(); } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java similarity index 68% rename from qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java rename to qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java index 2f28932..9965a1e 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/OnlineUserFilter.java @@ -1,21 +1,20 @@ package com.qiaoba.auth.filters; -import com.qiaoba.api.auth.service.AuthConfigApiService; import com.qiaoba.api.auth.constants.SecurityConstant; import com.qiaoba.api.auth.entity.dto.OnlineUserDto; -import com.qiaoba.auth.properties.AuthConfigProperties; +import com.qiaoba.api.auth.service.AuthConfigApiService; import com.qiaoba.api.auth.service.OnlineUserService; import com.qiaoba.api.auth.utils.TokenUtil; +import com.qiaoba.auth.properties.AuthConfigProperties; +import com.qiaoba.common.base.order.FilterOrder; import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.web.utils.ResponseUtil; import com.qiaoba.common.web.utils.UriUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.core.annotation.Order; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; @@ -26,28 +25,26 @@ import java.io.IOException; import java.util.Objects; /** - * 鉴权核心过滤器 + * 在线用户过滤器 * * @author ailanyin * @version 1.0 - * @since 2023-05-28 15:31:55 + * @since 2023/7/6 9:14 */ @RequiredArgsConstructor @Slf4j -public class AuthenticationCoreFilter extends OncePerRequestFilter { +@Order(FilterOrder.ONLINE_USER_FILTER_ORDER) +public class OnlineUserFilter extends OncePerRequestFilter { - private final RedisService redisService; - private final UserDetailsService userDetailsService; - private final OnlineUserService onlineUserService; private final AuthConfigProperties authConfigProperties; private final AuthConfigApiService authConfigApiService; - + private final RedisService redisService; + private final OnlineUserService onlineUserService; + private final UserDetailsService userDetailsService; @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain chain) throws ServletException, IOException { - log.debug("Start run AuthenticationCoreFilter, Uri: {}", request.getRequestURI()); + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + log.debug("Start run OnlineUserFilter, Uri: {}", request.getRequestURI()); // 白名单 放行 for (String uri : authConfigProperties.getWhitelist()) { if (UriUtil.match(uri, request.getRequestURI())) { @@ -84,13 +81,6 @@ public class AuthenticationCoreFilter extends OncePerRequestFilter { } } - // 更新 SecurityContextHolder Authentication, 为了保证 SecurityContext 上下文中 userDetails 是最新的 - if (Objects.nonNull(userDetails) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - chain.doFilter(request, response); } } diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/SecurityContextHolderFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/SecurityContextHolderFilter.java new file mode 100644 index 0000000..3ff8c09 --- /dev/null +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/SecurityContextHolderFilter.java @@ -0,0 +1,55 @@ +package com.qiaoba.auth.filters; + +import cn.hutool.core.util.StrUtil; +import com.qiaoba.api.auth.utils.TokenUtil; +import com.qiaoba.auth.properties.AuthConfigProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; + +/** + * 鉴权核心过滤器 + * + * @author ailanyin + * @version 1.0 + * @since 2023-05-28 15:31:55 + */ +@RequiredArgsConstructor +@Slf4j +public class SecurityContextHolderFilter extends OncePerRequestFilter { + + + private final UserDetailsService userDetailsService; + + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain chain) throws ServletException, IOException { + log.debug("Start run SecurityContextHolderFilter, Uri: {}", request.getRequestURI()); + + String username = TokenUtil.analyzeUsername(request); + if (StrUtil.isNotBlank(username)) { + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + // 更新 SecurityContextHolder Authentication, 为了保证 SecurityContext 上下文中 userDetails 是最新的 + if (Objects.nonNull(userDetails) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + chain.doFilter(request, response); + } +} 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 4e02980..bf02fbd 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,5 +1,6 @@ package com.qiaoba.auth.handler; +import cn.hutool.core.util.ObjectUtil; import com.qiaoba.api.auth.entity.LoginUser; import com.qiaoba.api.auth.service.OnlineUserService; import lombok.RequiredArgsConstructor; @@ -28,7 +29,9 @@ public class LogoutHandler implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 删除缓存中的用户信息 - LoginUser user = (LoginUser) authentication.getPrincipal(); - onlineUserService.deleteOne(user.getUsername(), user.getDeviceSn(), true); + if (ObjectUtil.isNotEmpty(authentication) && ObjectUtil.isNotEmpty(authentication.getPrincipal())) { + LoginUser user = (LoginUser) authentication.getPrincipal(); + onlineUserService.deleteOne(user.getUsername(), user.getDeviceSn(), true); + } } } diff --git a/qiaoba-auth/src/main/resources/META-INF/spring.factories b/qiaoba-auth/src/main/resources/META-INF/spring.factories index 4bb9578..a7e46a2 100644 --- a/qiaoba-auth/src/main/resources/META-INF/spring.factories +++ b/qiaoba-auth/src/main/resources/META-INF/spring.factories @@ -2,7 +2,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.qiaoba.auth.properties.AuthConfigProperties,\ com.qiaoba.auth.handler.AccessDeniedHandler,\ com.qiaoba.auth.handler.LogoutHandler,\ - com.qiaoba.auth.filters.AuthenticationCoreFilter,\ + com.qiaoba.auth.filters.OnlineUserFilter,\ + com.qiaoba.auth.filters.SecurityContextHolderFilter,\ com.qiaoba.auth.advice.SecurityExceptionAdvice,\ com.qiaoba.auth.aspectj.DataScopeAspect,\ com.qiaoba.auth.service.impl.OnlineUserServiceImpl,\ diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/order/FilterOrder.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/order/FilterOrder.java new file mode 100644 index 0000000..145de19 --- /dev/null +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/order/FilterOrder.java @@ -0,0 +1,22 @@ +package com.qiaoba.common.base.order; + +/** + * 过滤器执行顺序 + * + * @author ailanyin + * @version 1.0 + * @since 2023/7/6 9:22 + */ +public interface FilterOrder { + + /** + * 动态数据源过滤器-执行顺序(最高) + */ + int DYNAMIC_DATASOURCE_FILTER_ORDER = -10000; + + /** + * 在线用户过滤器 + */ + int ONLINE_USER_FILTER_ORDER = -9999; + +} 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 0989695..e445ff9 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 @@ -2,6 +2,7 @@ package com.qiaoba.common.web.utils; import cn.hutool.http.ContentType; import cn.hutool.json.JSONUtil; +import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.result.AjaxResult; import javax.servlet.http.HttpServletResponse; @@ -20,7 +21,7 @@ public class ResponseUtil { public static void response(HttpServletResponse response, String msg) throws IOException { response.setStatus(HttpServletResponse.SC_OK); response.setContentType(ContentType.JSON.getValue()); - response.setCharacterEncoding("UTF-8"); + response.setCharacterEncoding(BaseConstant.UTF8); PrintWriter writer = response.getWriter(); writer.write(msg); writer.close(); diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java index 4b8095d..7d13b91 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java @@ -9,6 +9,7 @@ import com.qiaoba.common.base.code.TenantErrorCode; import com.qiaoba.common.base.constants.BaseConstant; import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.context.BaseContext; +import com.qiaoba.common.base.order.FilterOrder; import com.qiaoba.common.database.config.DynamicDataSourceConfig; import com.qiaoba.common.web.utils.ResponseUtil; import com.qiaoba.common.web.utils.UriUtil; @@ -36,7 +37,7 @@ import java.util.Objects; * @since 2023-04-25 22:48:43 */ @Component -@Order(-10000) +@Order(FilterOrder.DYNAMIC_DATASOURCE_FILTER_ORDER) @Slf4j public class DynamicDataSourceFilter extends OncePerRequestFilter {