From 159ec6d9d4b04422b15993c933ebefbc019c8478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= <2270033969@qq.com> Date: Thu, 18 Apr 2024 18:01:40 +0800 Subject: [PATCH] =?UTF-8?q?:recycle:=20Refactoring=20code.=20=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E9=87=8D=E6=9E=84=E6=94=AF=E6=8C=81=20=E4=B8=80?= =?UTF-8?q?=E5=A5=97=E4=BB=A3=E7=A0=81=E4=B8=A4=E7=A7=8D=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pigx-app-server/pigx-app-server-biz/pom.xml | 217 +++++----- pigx-auth/pom.xml | 69 +++- .../pigx/auth/PigxAuthApplication.java | 3 +- .../AuthorizationServerConfiguration.java | 194 +++++---- .../CaptchaCacheServiceProvider.java | 2 +- .../pigx/auth/endpoint/ImageCodeEndpoint.java | 84 ++++ .../filter/AuthSecurityConfigProperties.java | 30 ++ .../support/filter/PasswordDecoderFilter.java | 139 +++++++ .../support/filter/ValidateCodeFilter.java | 179 +++++++++ ...PigxAuthenticationFailureEventHandler.java | 6 - ...m.anji.captcha.service.CaptchaCacheService | 1 + .../src/main/resources/logback-spring.xml | 6 + pigx-common/pigx-common-bom/pom.xml | 2 +- .../core/util/RepeatBodyRequestWrapper.java | 103 +++++ pigx-common/pigx-common-data/pom.xml | 3 +- .../data/mybatis/DruidSqlLogFilter.java | 3 - .../openfeign/PigxFeignClientsRegistrar.java | 379 +++++++++--------- .../GlobalExceptionConfiguration.java | 28 +- .../config/OpenAPIMetadataConfiguration.java | 6 + .../pigx-flow-engine-biz/pom.xml | 42 +- .../pigx-flow-task/pigx-flow-task-biz/pom.xml | 42 +- pigx-gateway/pom.xml | 12 - .../config/GatewayConfigProperties.java | 25 -- .../config/RouterFunctionConfiguration.java | 59 --- .../gateway/filter/PasswordDecoderFilter.java | 215 ---------- .../filter/ValidateCodeGatewayFilter.java | 199 --------- .../handler/ImageCodeCheckHandler.java | 66 --- .../handler/ImageCodeCreateHandler.java | 63 --- .../gateway/handler/ImageCodeMathHandler.java | 74 ---- ...m.anji.captcha.service.CaptchaCacheService | 1 - pigx-upms/pigx-upms-biz/pom.xml | 60 +-- .../pigx/admin/PigxAdminApplication.java | 2 - .../admin/controller/SysTokenController.java | 2 +- .../src/main/resources/logback-spring.xml | 2 +- pigx-visual/pigx-codegen/pom.xml | 52 ++- .../pigx/codegen/PigxCodeGenApplication.java | 2 +- pigx-visual/pigx-daemon-quartz/pom.xml | 46 ++- pigx-visual/pigx-mp-platform/pom.xml | 52 ++- .../pigx/mp/config/WxMpInitConfigRunner.java | 4 +- pigx-visual/pigx-pay-platform/pom.xml | 59 +-- pom.xml | 46 +-- 41 files changed, 1240 insertions(+), 1339 deletions(-) rename {pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config => pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint}/CaptchaCacheServiceProvider.java (95%) create mode 100644 pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/ImageCodeEndpoint.java create mode 100644 pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/AuthSecurityConfigProperties.java create mode 100755 pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/PasswordDecoderFilter.java create mode 100644 pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/ValidateCodeFilter.java create mode 100644 pigx-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService create mode 100644 pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/RepeatBodyRequestWrapper.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/GatewayConfigProperties.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCheckHandler.java delete mode 100644 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCreateHandler.java delete mode 100755 pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeMathHandler.java delete mode 100644 pigx-gateway/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService diff --git a/pigx-app-server/pigx-app-server-biz/pom.xml b/pigx-app-server/pigx-app-server-biz/pom.xml index 8abf71684..b464ebcd9 100644 --- a/pigx-app-server/pigx-app-server-biz/pom.xml +++ b/pigx-app-server/pigx-app-server-biz/pom.xml @@ -1,105 +1,124 @@ - 4.0.0 - - com.pig4cloud - pigx-app-server - 5.4.0 - + 4.0.0 + + com.pig4cloud + pigx-app-server + 5.4.0 + - pigx-app-server-biz + pigx-app-server-biz - - - - org.springframework.boot - spring-boot-starter-undertow - - - - org.springframework.boot - spring-boot-starter-web - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-discovery - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-nacos-config - - - - com.pig4cloud - pigx-common-data - - - - com.pig4cloud - pigx-common-security - - - - com.pig4cloud - pigx-common-xss - - - - com.pig4cloud - pigx-common-sentinel - - - - com.pig4cloud - pigx-common-feign - - - - com.pig4cloud - pigx-app-server-api - 5.4.0 - - - - com.pig4cloud - pigx-common-log - - - - com.baomidou - mybatis-plus-spring-boot3-starter - - - - com.alibaba - druid-spring-boot-3-starter - - - - com.mysql - mysql-connector-j - - - - com.pig4cloud - pigx-common-swagger - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - io.fabric8 - docker-maven-plugin - - - + + + + org.springframework.boot + spring-boot-starter-undertow + + + + org.springframework.boot + spring-boot-starter-web + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + com.pig4cloud + pigx-common-data + + + + com.pig4cloud + pigx-common-security + + + + com.pig4cloud + pigx-common-xss + + + + com.pig4cloud + pigx-common-sentinel + + + + com.pig4cloud + pigx-common-feign + + + + com.pig4cloud + pigx-app-server-api + 5.4.0 + + + + com.pig4cloud + pigx-common-log + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + com.alibaba + druid-spring-boot-3-starter + + + + com.mysql + mysql-connector-j + + + + com.pig4cloud + pigx-common-swagger + + + + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-auth/pom.xml b/pigx-auth/pom.xml index bf126ed52..286a3afca 100644 --- a/pigx-auth/pom.xml +++ b/pigx-auth/pom.xml @@ -78,6 +78,23 @@ org.springframework.boot spring-boot-starter-freemarker + + + cn.hutool + hutool-crypto + + + + io.springboot.plugin + captcha-core + ${captcha.image.version} + + + + io.springboot.plugin + spring-boot-starter-captcha + ${captcha.version} + org.springframework.boot @@ -90,27 +107,35 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - io.fabric8 - docker-maven-plugin - - false - - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java index eeda3d098..74e5d3f9c 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/PigxAuthApplication.java @@ -16,7 +16,6 @@ package com.pig4cloud.pigx.auth; -import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure; import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -28,7 +27,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; */ @EnablePigxFeignClients @EnableDiscoveryClient -@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class) +@SpringBootApplication public class PigxAuthApplication { public static void main(String[] args) { diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfiguration.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfiguration.java index 595450aec..8bfa3522a 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfiguration.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/config/AuthorizationServerConfiguration.java @@ -21,6 +21,8 @@ import com.pig4cloud.pigx.auth.support.core.CustomeOAuth2TokenCustomizer; import com.pig4cloud.pigx.auth.support.core.FormIdentityLoginConfigurer; import com.pig4cloud.pigx.auth.support.core.PigxDaoAuthenticationProvider; import com.pig4cloud.pigx.auth.support.core.PigxOAuth2RefreshTokenAuthenticationConverter; +import com.pig4cloud.pigx.auth.support.filter.PasswordDecoderFilter; +import com.pig4cloud.pigx.auth.support.filter.ValidateCodeFilter; import com.pig4cloud.pigx.auth.support.handler.PigxAuthenticationFailureEventHandler; import com.pig4cloud.pigx.auth.support.handler.PigxAuthenticationSuccessEventHandler; import com.pig4cloud.pigx.auth.support.password.OAuth2ResourceOwnerPasswordAuthenticationConverter; @@ -31,6 +33,7 @@ import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.security.handler.FormAuthenticationFailureHandler; import com.pig4cloud.pigx.common.security.handler.SsoLogoutSuccessHandler; import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -44,11 +47,15 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori import org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator; import org.springframework.security.oauth2.server.authorization.token.OAuth2RefreshTokenGenerator; import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator; -import org.springframework.security.oauth2.server.authorization.web.authentication.*; +import org.springframework.security.oauth2.server.authorization.web.authentication.DelegatingAuthenticationConverter; +import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeAuthenticationConverter; +import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AuthorizationCodeRequestAuthenticationConverter; +import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2ClientCredentialsAuthenticationConverter; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationConverter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @@ -57,111 +64,122 @@ import java.util.Arrays; /** * @author lengleng * @date 2022/5/27 - * + *

* 认证服务器配置 */ @Configuration @RequiredArgsConstructor public class AuthorizationServerConfiguration { - private final OAuth2AuthorizationService authorizationService; + private final OAuth2AuthorizationService authorizationService; - @Bean - @Order(Ordered.HIGHEST_PRECEDENCE) - public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http, - PigxAuthenticationSuccessEventHandler successEventHandler, - PigxAuthenticationFailureEventHandler failureEventHandler) throws Exception { - OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer(); + private final PasswordDecoderFilter passwordDecoderFilter; - http.with(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> {// 个性化认证授权端点 - tokenEndpoint.accessTokenRequestConverter(accessTokenRequestConverter()) // 注入自定义的授权认证Converter - .accessTokenResponseHandler(successEventHandler) // 登录成功处理器 - .errorResponseHandler(failureEventHandler);// 登录失败处理器 - }).clientAuthentication(oAuth2ClientAuthenticationConfigurer -> // 个性化客户端认证 - oAuth2ClientAuthenticationConfigurer.errorResponseHandler(failureEventHandler))// 处理客户端认证异常 - .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint// 授权码端点个性化confirm页面 - .consentPage(SecurityConstants.CUSTOM_CONSENT_PAGE_URI)),Customizer.withDefaults()); + private final ValidateCodeFilter validateCodeFilter; - AntPathRequestMatcher[] requestMatchers = new AntPathRequestMatcher[] { - AntPathRequestMatcher.antMatcher("/token/**"), AntPathRequestMatcher.antMatcher("/actuator/**"), - AntPathRequestMatcher.antMatcher("/css/**"), AntPathRequestMatcher.antMatcher("/error") }; + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + @ConditionalOnProperty(value = "security.micro", matchIfMissing = true) + public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http, + PigxAuthenticationSuccessEventHandler successEventHandler, + PigxAuthenticationFailureEventHandler failureEventHandler) throws Exception { + // 增加验证码过滤器 + http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class); + // 增加密码解密过滤器 + http.addFilterBefore(passwordDecoderFilter, UsernamePasswordAuthenticationFilter.class); - http.authorizeHttpRequests(authorizeRequests -> { - // 自定义接口、端点暴露 - authorizeRequests.requestMatchers(requestMatchers).permitAll(); - authorizeRequests.anyRequest().authenticated(); - }) - .with(authorizationServerConfigurer.authorizationService(authorizationService)// redis存储token的实现 - .authorizationServerSettings( - AuthorizationServerSettings.builder().issuer(SecurityConstants.PIGX_LICENSE).build()), Customizer.withDefaults()); - http.with(new FormIdentityLoginConfigurer(), Customizer.withDefaults()); - DefaultSecurityFilterChain securityFilterChain = http.build(); + OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer(); + http.with(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> {// 个性化认证授权端点 + tokenEndpoint.accessTokenRequestConverter(accessTokenRequestConverter()) // 注入自定义的授权认证Converter + .accessTokenResponseHandler(successEventHandler) // 登录成功处理器 + .errorResponseHandler(failureEventHandler);// 登录失败处理器 + }).clientAuthentication(oAuth2ClientAuthenticationConfigurer -> // 个性化客户端认证 + oAuth2ClientAuthenticationConfigurer.errorResponseHandler(failureEventHandler))// 处理客户端认证异常 + .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint// 授权码端点个性化confirm页面 + .consentPage(SecurityConstants.CUSTOM_CONSENT_PAGE_URI)), Customizer.withDefaults()); - // 注入自定义授权模式实现 - addCustomOAuth2GrantAuthenticationProvider(http); - return securityFilterChain; - } + AntPathRequestMatcher[] requestMatchers = new AntPathRequestMatcher[]{ + AntPathRequestMatcher.antMatcher("/token/**"), AntPathRequestMatcher.antMatcher("/actuator/**"), + AntPathRequestMatcher.antMatcher("/css/**"), AntPathRequestMatcher.antMatcher("/error")}; - /** - * 令牌生成规则实现
- * client:username:uuid - * @return OAuth2TokenGenerator - */ - @Bean - public OAuth2TokenGenerator oAuth2TokenGenerator() { - CustomeOAuth2AccessTokenGenerator accessTokenGenerator = new CustomeOAuth2AccessTokenGenerator(); - // 注入Token 增加关联用户信息 - accessTokenGenerator.setAccessTokenCustomizer(new CustomeOAuth2TokenCustomizer()); - return new DelegatingOAuth2TokenGenerator(accessTokenGenerator, new OAuth2RefreshTokenGenerator()); - } + http.authorizeHttpRequests(authorizeRequests -> { + // 自定义接口、端点暴露 + authorizeRequests.requestMatchers(requestMatchers).permitAll(); + authorizeRequests.anyRequest().authenticated(); + }) + .with(authorizationServerConfigurer.authorizationService(authorizationService)// redis存储token的实现 + .authorizationServerSettings( + AuthorizationServerSettings.builder().issuer(SecurityConstants.PIGX_LICENSE).build()), Customizer.withDefaults()); + http.with(new FormIdentityLoginConfigurer(), Customizer.withDefaults()); + DefaultSecurityFilterChain securityFilterChain = http.build(); - @Bean - public AuthenticationFailureHandler authenticationFailureHandler() { - return new FormAuthenticationFailureHandler(); - } + // 注入自定义授权模式实现 + addCustomOAuth2GrantAuthenticationProvider(http); + return securityFilterChain; + } - @Bean - public LogoutSuccessHandler logoutSuccessHandler() { - return new SsoLogoutSuccessHandler(); - } + /** + * 令牌生成规则实现
+ * client:username:uuid + * + * @return OAuth2TokenGenerator + */ + @Bean + public OAuth2TokenGenerator oAuth2TokenGenerator() { + CustomeOAuth2AccessTokenGenerator accessTokenGenerator = new CustomeOAuth2AccessTokenGenerator(); + // 注入Token 增加关联用户信息 + accessTokenGenerator.setAccessTokenCustomizer(new CustomeOAuth2TokenCustomizer()); + return new DelegatingOAuth2TokenGenerator(accessTokenGenerator, new OAuth2RefreshTokenGenerator()); + } - /** - * request -> xToken 注入请求转换器 - * @return DelegatingAuthenticationConverter - */ - private AuthenticationConverter accessTokenRequestConverter() { - return new DelegatingAuthenticationConverter(Arrays.asList( - new OAuth2ResourceOwnerPasswordAuthenticationConverter(), - new OAuth2ResourceOwnerSmsAuthenticationConverter(), new PigxOAuth2RefreshTokenAuthenticationConverter(), - new OAuth2ClientCredentialsAuthenticationConverter(), - new OAuth2AuthorizationCodeAuthenticationConverter(), - new OAuth2AuthorizationCodeRequestAuthenticationConverter())); - } + @Bean + public AuthenticationFailureHandler authenticationFailureHandler() { + return new FormAuthenticationFailureHandler(); + } - /** - * 注入授权模式实现提供方 - * - * 1. 密码模式
- * 2. 短信登录
- * - */ - @SuppressWarnings("unchecked") - private void addCustomOAuth2GrantAuthenticationProvider(HttpSecurity http) { - AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); - OAuth2AuthorizationService authorizationService = http.getSharedObject(OAuth2AuthorizationService.class); + @Bean + public LogoutSuccessHandler logoutSuccessHandler() { + return new SsoLogoutSuccessHandler(); + } - OAuth2ResourceOwnerPasswordAuthenticationProvider resourceOwnerPasswordAuthenticationProvider = new OAuth2ResourceOwnerPasswordAuthenticationProvider( - authenticationManager, authorizationService, oAuth2TokenGenerator()); + /** + * request -> xToken 注入请求转换器 + * + * @return DelegatingAuthenticationConverter + */ + @Bean + public AuthenticationConverter accessTokenRequestConverter() { + return new DelegatingAuthenticationConverter(Arrays.asList( + new OAuth2ResourceOwnerPasswordAuthenticationConverter(), + new OAuth2ResourceOwnerSmsAuthenticationConverter(), new PigxOAuth2RefreshTokenAuthenticationConverter(), + new OAuth2ClientCredentialsAuthenticationConverter(), + new OAuth2AuthorizationCodeAuthenticationConverter(), + new OAuth2AuthorizationCodeRequestAuthenticationConverter())); + } - OAuth2ResourceOwnerSmsAuthenticationProvider resourceOwnerSmsAuthenticationProvider = new OAuth2ResourceOwnerSmsAuthenticationProvider( - authenticationManager, authorizationService, oAuth2TokenGenerator()); + /** + * 注入授权模式实现提供方 + *

+ * 1. 密码模式
+ * 2. 短信登录
+ */ + @SuppressWarnings("unchecked") + private void addCustomOAuth2GrantAuthenticationProvider(HttpSecurity http) { + AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); + OAuth2AuthorizationService authorizationService = http.getSharedObject(OAuth2AuthorizationService.class); - // 处理 UsernamePasswordAuthenticationToken - http.authenticationProvider(new PigxDaoAuthenticationProvider()); - // 处理 OAuth2ResourceOwnerPasswordAuthenticationToken - http.authenticationProvider(resourceOwnerPasswordAuthenticationProvider); - // 处理 OAuth2ResourceOwnerSmsAuthenticationToken - http.authenticationProvider(resourceOwnerSmsAuthenticationProvider); - } + OAuth2ResourceOwnerPasswordAuthenticationProvider resourceOwnerPasswordAuthenticationProvider = new OAuth2ResourceOwnerPasswordAuthenticationProvider( + authenticationManager, authorizationService, oAuth2TokenGenerator()); + + OAuth2ResourceOwnerSmsAuthenticationProvider resourceOwnerSmsAuthenticationProvider = new OAuth2ResourceOwnerSmsAuthenticationProvider( + authenticationManager, authorizationService, oAuth2TokenGenerator()); + + // 处理 UsernamePasswordAuthenticationToken + http.authenticationProvider(new PigxDaoAuthenticationProvider()); + // 处理 OAuth2ResourceOwnerPasswordAuthenticationToken + http.authenticationProvider(resourceOwnerPasswordAuthenticationProvider); + // 处理 OAuth2ResourceOwnerSmsAuthenticationToken + http.authenticationProvider(resourceOwnerSmsAuthenticationProvider); + } } diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/CaptchaCacheServiceProvider.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/CaptchaCacheServiceProvider.java similarity index 95% rename from pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/CaptchaCacheServiceProvider.java rename to pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/CaptchaCacheServiceProvider.java index 1b582905a..371b78c93 100644 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/CaptchaCacheServiceProvider.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/CaptchaCacheServiceProvider.java @@ -1,4 +1,4 @@ -package com.pig4cloud.pigx.gateway.config; +package com.pig4cloud.pigx.auth.endpoint; import com.anji.captcha.service.CaptchaCacheService; import org.springframework.beans.factory.annotation.Autowired; diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/ImageCodeEndpoint.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/ImageCodeEndpoint.java new file mode 100644 index 000000000..b8920c1f8 --- /dev/null +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/ImageCodeEndpoint.java @@ -0,0 +1,84 @@ +package com.pig4cloud.pigx.auth.endpoint; + +import com.anji.captcha.model.vo.CaptchaVO; +import com.anji.captcha.service.CaptchaService; +import com.pig4cloud.pigx.common.core.constant.CacheConstants; +import com.pig4cloud.pigx.common.core.constant.CommonConstants; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.core.util.SpringContextHolder; +import io.springboot.captcha.ArithmeticCaptcha; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.concurrent.TimeUnit; + +/** + * 验证码相关的接口 + * + * @author lengleng + * @date 2022/6/27 + */ +@RestController +@RequestMapping("/code") +@RequiredArgsConstructor +public class ImageCodeEndpoint { + + private static final Integer DEFAULT_IMAGE_WIDTH = 100; + + private static final Integer DEFAULT_IMAGE_HEIGHT = 40; + + private final StringRedisTemplate redisTemplate; + + /** + * 创建图形验证码 + */ + @SneakyThrows + @GetMapping("/image") + public void image(String randomStr, HttpServletResponse response) { + ArithmeticCaptcha captcha = new ArithmeticCaptcha(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT); + + String result = captcha.text(); + redisTemplate.opsForValue() + .set(CacheConstants.DEFAULT_CODE_KEY + randomStr, result, SecurityConstants.CODE_TIME, TimeUnit.SECONDS); + // 转换流信息写出 + captcha.out(response.getOutputStream()); + } + + /** + * 行为 + * 创建滑块图形验证码 + */ + @SneakyThrows + @GetMapping("/create") + public R behavior() { + CaptchaVO vo = new CaptchaVO(); + vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); + CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); + return R.ok(captchaService.get(vo)); + } + + /** + * 行为 + * 创建滑块图形验证码 + */ + @SneakyThrows + @PostMapping("/check") + public R check(HttpServletRequest request) { + CaptchaVO vo = new CaptchaVO(); + vo.setPointJson(request.getParameter("pointJson")); + vo.setToken(request.getParameter("token")); + vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); + + CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); + return R.ok(captchaService.check(vo)); + } + +} diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/AuthSecurityConfigProperties.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/AuthSecurityConfigProperties.java new file mode 100644 index 000000000..4c4b547c4 --- /dev/null +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/AuthSecurityConfigProperties.java @@ -0,0 +1,30 @@ +package com.pig4cloud.pigx.auth.support.filter; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; + +/** + * @author lengleng + * @date 2020/10/4 + *

+ * 网关配置文件 + */ +@Data +@Component +@RefreshScope +@ConfigurationProperties("security") +public class AuthSecurityConfigProperties { + + /** + * 是否是微服务架构 + */ + private boolean isMicro; + + /** + * 网关解密登录前端密码 秘钥 + */ + private String encodeKey; + +} diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/PasswordDecoderFilter.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/PasswordDecoderFilter.java new file mode 100755 index 000000000..ef3fbf8d3 --- /dev/null +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/PasswordDecoderFilter.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pig4cloud.pigx.auth.support.filter; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.symmetric.AES; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.pig4cloud.pigx.common.core.constant.CacheConstants; +import com.pig4cloud.pigx.common.core.constant.CommonConstants; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.constant.enums.EncFlagTypeEnum; +import com.pig4cloud.pigx.common.core.util.RepeatBodyRequestWrapper; +import com.pig4cloud.pigx.common.core.util.WebUtils; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.util.Map; + +/** + * @author lengleng + * @date 2019 /2/1 密码解密工具类 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class PasswordDecoderFilter extends OncePerRequestFilter { + + private final AuthSecurityConfigProperties authSecurityConfigProperties; + + private final StringRedisTemplate redisTemplate; + + private static final String PASSWORD = "password"; + + private static final String KEY_ALGORITHM = "AES"; + + static { + // 关闭hutool 强制关闭Bouncy Castle库的依赖 + SecureUtil.disableBouncyCastle(); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException { + // 不是登录请求,直接向下执行 + if (!StrUtil.containsAnyIgnoreCase(request.getRequestURI(), SecurityConstants.OAUTH_TOKEN_URL)) { + chain.doFilter(request, response); + return; + } + + // 2. 刷新token类型,直接向下执行 + String grantType = request.getParameter("grant_type"); + if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) { + chain.doFilter(request, response); + return; + } + + // 3. 判断客户端是否需要解密,明文传输直接向下执行 + if (!isEncClient(request)) { + chain.doFilter(request, response); + return; } + + // 将请求流转换为可多次读取的请求流 + RepeatBodyRequestWrapper requestWrapper = new RepeatBodyRequestWrapper(request); + Map parameterMap = requestWrapper.getParameterMap(); + + // 构建前端对应解密AES 因子 + AES aes = new AES(Mode.CFB, Padding.NoPadding, + new SecretKeySpec(authSecurityConfigProperties.getEncodeKey().getBytes(), KEY_ALGORITHM), + new IvParameterSpec(authSecurityConfigProperties.getEncodeKey().getBytes())); + + parameterMap.forEach((k, v) -> { + String[] values = parameterMap.get(k); + if (!PASSWORD.equals(k) || ArrayUtil.isEmpty(values)) { + return; + } + + // 解密密码 + String decryptPassword = aes.decryptStr(values[0]); + parameterMap.put(k, new String[]{decryptPassword}); + }); + chain.doFilter(requestWrapper, response); + } + + /** + * 根据请求的clientId 查询客户端配置是否是加密传输 + * + * @param request 请求上下文 + * @return true 加密传输 、 false 原文传输 + */ + private boolean isEncClient(HttpServletRequest request) { + String header = request.getHeader(HttpHeaders.AUTHORIZATION); + String clientId = WebUtils.extractClientId(header).orElse(null); + // 获取租户拼接区分租户的key + String tenantId = request.getHeader(CommonConstants.TENANT_ID); + String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId, + CacheConstants.CLIENT_FLAG, clientId); + + String val = redisTemplate.opsForValue().get(key); + + // 当配置不存在时,默认需要解密 + if (val == null) { + return true; + } + + JSONObject information = JSONUtil.parseObj(val); + return !StrUtil.equals(EncFlagTypeEnum.NO.getType(), information.getStr(CommonConstants.ENC_FLAG)); + } + +} diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/ValidateCodeFilter.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/ValidateCodeFilter.java new file mode 100644 index 000000000..5995ddaf5 --- /dev/null +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/filter/ValidateCodeFilter.java @@ -0,0 +1,179 @@ +package com.pig4cloud.pigx.auth.support.filter; + +/** + * 登录前处理器 + * + * @author lengleng + * @date 2024/4/3 + */ + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.anji.captcha.model.vo.CaptchaVO; +import com.anji.captcha.service.CaptchaService; +import com.pig4cloud.pigx.common.core.constant.CacheConstants; +import com.pig4cloud.pigx.common.core.constant.CommonConstants; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.core.constant.enums.CaptchaFlagTypeEnum; +import com.pig4cloud.pigx.common.core.exception.ValidateCodeException; +import com.pig4cloud.pigx.common.core.util.SpringContextHolder; +import com.pig4cloud.pigx.common.core.util.WebUtils; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +/** + * @author lbw + * @date 2024-01-06 + *

+ * 登录前置处理器: 前端密码传输密文解密,验证码处理 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class ValidateCodeFilter extends OncePerRequestFilter { + + + private final StringRedisTemplate redisTemplate; + + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + + String requestUrl = request.getServletPath(); + + // 不是登录URL 请求直接跳过 + if (!SecurityConstants.OAUTH_TOKEN_URL.equals(requestUrl)) { + filterChain.doFilter(request, response); + return; + } + + // 如果登录URL 但是刷新token的请求,直接向下执行 + String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); + if (StrUtil.containsAny(grantType, SecurityConstants.REFRESH_TOKEN)) { + filterChain.doFilter(request, response); + return; + } + + // mobile模式, 如果请求不包含mobile 参数直接 + String mobile = request.getParameter(SecurityConstants.GRANT_MOBILE); + if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) { + throw new OAuth2AuthenticationException(SecurityConstants.GRANT_MOBILE); + } + + // mobile模式, 社交登录模式不校验验证码直接跳过 + if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) { + filterChain.doFilter(request, response); + return; + } + + // 判断客户端是否跳过检验 + if (!isCheckCaptchaClient(request)) { + filterChain.doFilter(request, response); + return; + } + + // 校验验证码 1. 客户端开启验证码 2. 短信模式 + try { + checkCode(); + filterChain.doFilter(request, response); + } catch (ValidateCodeException validateCodeException) { + throw new OAuth2AuthenticationException(validateCodeException.getMessage()); + } + } + + /** + * 校验验证码 + */ + private void checkCode() throws ValidateCodeException { + HttpServletRequest request = WebUtils.getRequest(); + String code = request.getParameter("code"); + + if (StrUtil.isBlank(code)) { + throw new ValidateCodeException("验证码不能为空"); + } + + String randomStr = request.getParameter("randomStr"); + + // https://gitee.com/log4j/pig/issues/IWA0D + String mobile = request.getParameter("mobile"); + if (StrUtil.isNotBlank(mobile)) { + randomStr = mobile; + } + + // 若是滑块登录 + if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) { + CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); + CaptchaVO vo = new CaptchaVO(); + vo.setCaptchaVerification(code); + vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); + if (!captchaService.verification(vo).isSuccess()) { + throw new ValidateCodeException("验证码不能为空"); + } + return; + } + + + String key = CacheConstants.DEFAULT_CODE_KEY + randomStr; + if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) { + throw new ValidateCodeException("验证码不合法"); + } + + Object codeObj = redisTemplate.opsForValue().get(key); + + if (codeObj == null) { + throw new ValidateCodeException("验证码不合法"); + } + + String saveCode = codeObj.toString(); + if (StrUtil.isBlank(saveCode)) { + redisTemplate.delete(key); + throw new ValidateCodeException("验证码不合法"); + } + + if (!StrUtil.equals(saveCode, code)) { + redisTemplate.delete(key); + throw new ValidateCodeException("验证码不合法"); + } + + redisTemplate.delete(key); + } + + /** + * 是否需要校验客户端,根据client 查询客户端配置 + * + * @param request 请求 + * @return true 需要校验, false 不需要校验 + */ + private boolean isCheckCaptchaClient(HttpServletRequest request) { + String header = request.getHeader(HttpHeaders.AUTHORIZATION); + String clientId = WebUtils.extractClientId(header).orElse(null); + // 获取租户拼接区分租户的key + String tenantId = request.getHeader(CommonConstants.TENANT_ID); + String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId, + CacheConstants.CLIENT_FLAG, clientId); + + String val = redisTemplate.opsForValue().get(key); + + // 当配置不存在时,不用校验 + if (val == null) { + return false; + } + + JSONObject information = JSONUtil.parseObj(val); + return !StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG)); + } +} diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/handler/PigxAuthenticationFailureEventHandler.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/handler/PigxAuthenticationFailureEventHandler.java index 09700a2be..b8e831fcd 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/handler/PigxAuthenticationFailureEventHandler.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/support/handler/PigxAuthenticationFailureEventHandler.java @@ -23,7 +23,6 @@ import com.pig4cloud.pigx.common.core.constant.CacheConstants; import com.pig4cloud.pigx.common.core.constant.CommonConstants; import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.core.util.KeyStrResolver; -import com.pig4cloud.pigx.common.core.util.MsgUtils; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.core.util.WebUtils; import com.pig4cloud.pigx.common.data.resolver.ParamResolver; @@ -163,11 +162,6 @@ public class PigxAuthenticationFailureEventHandler implements AuthenticationFail errorMessage = exception.getLocalizedMessage(); } - // 手机号登录 - String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE); - if (SecurityConstants.APP.equals(grantType)) { - errorMessage = MsgUtils.getSecurityMessage("AbstractUserDetailsAuthenticationProvider.smsBadCredentials"); - } this.errorHttpResponseConverter.write(R.failed(errorMessage), MediaType.APPLICATION_JSON, httpResponse); } diff --git a/pigx-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService b/pigx-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService new file mode 100644 index 000000000..39e4ea0c5 --- /dev/null +++ b/pigx-auth/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService @@ -0,0 +1 @@ +com.pig4cloud.pigx.auth.endpoint.CaptchaCacheServiceProvider diff --git a/pigx-auth/src/main/resources/logback-spring.xml b/pigx-auth/src/main/resources/logback-spring.xml index ef137181c..13d4db2e5 100644 --- a/pigx-auth/src/main/resources/logback-spring.xml +++ b/pigx-auth/src/main/resources/logback-spring.xml @@ -79,6 +79,12 @@ + + + + + + diff --git a/pigx-common/pigx-common-bom/pom.xml b/pigx-common/pigx-common-bom/pom.xml index 657e3ba9d..317257eea 100644 --- a/pigx-common/pigx-common-bom/pom.xml +++ b/pigx-common/pigx-common-bom/pom.xml @@ -28,7 +28,7 @@ 8.4.1.jre8 8.1.2.192 6.2.0 - 3.0.3 + 3.0.5 2.1.0 2.2.14 4.6.0 diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/RepeatBodyRequestWrapper.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/RepeatBodyRequestWrapper.java new file mode 100644 index 000000000..574b0a628 --- /dev/null +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/RepeatBodyRequestWrapper.java @@ -0,0 +1,103 @@ +/* + * Copyright 2023-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pig4cloud.pigx.common.core.util; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StreamUtils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; + +/** + * Request包装类:允许 body 重复读取 + * + * @author Hccake + */ +@Slf4j +public class RepeatBodyRequestWrapper extends HttpServletRequestWrapper { + + private final byte[] bodyByteArray; + + private final Map parameterMap; + + public RepeatBodyRequestWrapper(HttpServletRequest request) { + super(request); + this.bodyByteArray = getByteBody(request); + this.parameterMap = super.getParameterMap(); + } + + @Override + public BufferedReader getReader() { + return ObjectUtils.isEmpty(this.bodyByteArray) ? null + : new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.bodyByteArray); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + // doNoting + } + + @Override + public int read() { + return byteArrayInputStream.read(); + } + }; + } + + private static byte[] getByteBody(HttpServletRequest request) { + byte[] body = new byte[0]; + try { + body = StreamUtils.copyToByteArray(request.getInputStream()); + } + catch (IOException e) { + log.error("解析流中数据异常", e); + } + return body; + } + + /** + * 重写 getParameterMap() 方法 解决 undertow 中流被读取后,会进行标记,从而导致无法正确获取 body 中的表单数据的问题 + * @return Map parameterMap + */ + @Override + public Map getParameterMap() { + return this.parameterMap; + } + +} diff --git a/pigx-common/pigx-common-data/pom.xml b/pigx-common/pigx-common-data/pom.xml index 0b3d0fb63..fbd3c3b87 100644 --- a/pigx-common/pigx-common-data/pom.xml +++ b/pigx-common/pigx-common-data/pom.xml @@ -52,7 +52,8 @@ com.alibaba - druid-spring-boot-3-starter + druid + true diff --git a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/DruidSqlLogFilter.java b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/DruidSqlLogFilter.java index 1dd957acb..08c14a12f 100644 --- a/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/DruidSqlLogFilter.java +++ b/pigx-common/pigx-common-data/src/main/java/com/pig4cloud/pigx/common/data/mybatis/DruidSqlLogFilter.java @@ -25,7 +25,6 @@ import com.alibaba.druid.filter.FilterEventAdapter; import com.alibaba.druid.proxy.jdbc.JdbcParameter; import com.alibaba.druid.proxy.jdbc.ResultSetProxy; import com.alibaba.druid.proxy.jdbc.StatementProxy; -import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; @@ -34,7 +33,6 @@ import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.util.StringUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Import; import java.sql.SQLException; import java.time.temporal.TemporalAccessor; @@ -53,7 +51,6 @@ import java.util.Map; */ @Slf4j @RequiredArgsConstructor -@Import(DruidDataSourceAutoConfigure.class) public class DruidSqlLogFilter extends FilterEventAdapter { private static final SQLUtils.FormatOption FORMAT_OPTION = new SQLUtils.FormatOption(false, false); diff --git a/pigx-common/pigx-common-feign/src/main/java/org/springframework/cloud/openfeign/PigxFeignClientsRegistrar.java b/pigx-common/pigx-common-feign/src/main/java/org/springframework/cloud/openfeign/PigxFeignClientsRegistrar.java index 3eb609111..b5d782e20 100644 --- a/pigx-common/pigx-common-feign/src/main/java/org/springframework/cloud/openfeign/PigxFeignClientsRegistrar.java +++ b/pigx-common/pigx-common-feign/src/main/java/org/springframework/cloud/openfeign/PigxFeignClientsRegistrar.java @@ -17,7 +17,6 @@ package org.springframework.cloud.openfeign; -import com.pig4cloud.pigx.common.feign.PigxFeignAutoConfiguration; import lombok.Getter; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.config.BeanDefinitionHolder; @@ -31,7 +30,6 @@ import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; -import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -48,226 +46,229 @@ import java.util.Map; * feign 自动配置功能 from mica */ public class PigxFeignClientsRegistrar - implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware { + implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware, EnvironmentAware { - private final static String BASE_URL = "http://127.0.0.1:${server.port}${server.servlet.context-path}"; + private final static String BASE_URL = "http://127.0.0.1:${server.port}${server.servlet.context-path}"; - @Getter - private ClassLoader beanClassLoader; + @Getter + private ClassLoader beanClassLoader; - @Getter - private Environment environment; + @Getter + private Environment environment; - @Override - public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { - registerFeignClients(registry); - } + @Override + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { + registerFeignClients(registry); + } - @Override - public void setBeanClassLoader(ClassLoader classLoader) { - this.beanClassLoader = classLoader; - } + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } - private void registerFeignClients(BeanDefinitionRegistry registry) { - List feignClients = new ArrayList<>(); + private void registerFeignClients(BeanDefinitionRegistry registry) { + List feignClients = new ArrayList<>(); - // 支持 springboot 2.7 + 最新版本的配置方式 - ImportCandidates.load(FeignClient.class, getBeanClassLoader()).forEach(feignClients::add); + // 支持 springboot 2.7 + 最新版本的配置方式 + ImportCandidates.load(FeignClient.class, getBeanClassLoader()).forEach(feignClients::add); - // 如果 spring.factories 里为空 - if (feignClients.isEmpty()) { - return; - } - for (String className : feignClients) { - try { - Class clazz = beanClassLoader.loadClass(className); - AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, - FeignClient.class); - if (attributes == null) { - continue; - } - // 如果已经存在该 bean,支持原生的 Feign - if (registry.containsBeanDefinition(className)) { - continue; - } + // 如果 spring.factories 里为空 + if (feignClients.isEmpty()) { + return; + } + for (String className : feignClients) { + try { + Class clazz = beanClassLoader.loadClass(className); + AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(clazz, + FeignClient.class); + if (attributes == null) { + continue; + } - registerClientConfiguration(registry, getClientName(attributes), className, - attributes.get("configuration")); + // 如果是单体项目自动注入 & url 为空 + Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true); + // 如果已经存在该 bean,支持原生的 Feign + if (registry.containsBeanDefinition(className) && isMicro) { + continue; + } - validate(attributes); - BeanDefinitionBuilder definition = BeanDefinitionBuilder - .genericBeanDefinition(FeignClientFactoryBean.class); - definition.addPropertyValue("url", getUrl(attributes)); - definition.addPropertyValue("path", getPath(attributes)); - String name = getName(attributes); - definition.addPropertyValue("name", name); + registerClientConfiguration(registry, getClientName(attributes), className, + attributes.get("configuration")); - // 兼容最新版本的 spring-cloud-openfeign,尚未发布 - StringBuilder aliasBuilder = new StringBuilder(18); - if (attributes.containsKey("contextId")) { - String contextId = getContextId(attributes); - aliasBuilder.append(contextId); - definition.addPropertyValue("contextId", contextId); - } - else { - aliasBuilder.append(name); - } + validate(attributes); + BeanDefinitionBuilder definition = BeanDefinitionBuilder + .genericBeanDefinition(FeignClientFactoryBean.class); + definition.addPropertyValue("url", getUrl(attributes)); + definition.addPropertyValue("path", getPath(attributes)); + String name = getName(attributes); + definition.addPropertyValue("name", name); - definition.addPropertyValue("type", className); - definition.addPropertyValue("dismiss404", - Boolean.parseBoolean(String.valueOf(attributes.get("dismiss404")))); - Object fallbackFactory = attributes.get("fallbackFactory"); - if (fallbackFactory != null) { - definition.addPropertyValue("fallbackFactory", fallbackFactory instanceof Class ? fallbackFactory - : ClassUtils.resolveClassName(fallbackFactory.toString(), null)); - } - definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory")); - definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); + // 兼容最新版本的 spring-cloud-openfeign,尚未发布 + StringBuilder aliasBuilder = new StringBuilder(18); + if (attributes.containsKey("contextId")) { + String contextId = getContextId(attributes); + aliasBuilder.append(contextId); + definition.addPropertyValue("contextId", contextId); + } else { + aliasBuilder.append(name); + } - AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); + definition.addPropertyValue("type", className); + definition.addPropertyValue("dismiss404", + Boolean.parseBoolean(String.valueOf(attributes.get("dismiss404")))); + Object fallbackFactory = attributes.get("fallbackFactory"); + if (fallbackFactory != null) { + definition.addPropertyValue("fallbackFactory", fallbackFactory instanceof Class ? fallbackFactory + : ClassUtils.resolveClassName(fallbackFactory.toString(), null)); + } + definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory")); + definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); - // alias - String alias = aliasBuilder.append("FeignClient").toString(); + AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); - // has a default, won't be null - boolean primary = (Boolean) attributes.get("primary"); + // alias + String alias = aliasBuilder.append("FeignClient").toString(); - beanDefinition.setPrimary(primary); + // has a default, won't be null + boolean primary = (Boolean) attributes.get("primary"); - String qualifier = getQualifier(attributes); - if (StringUtils.hasText(qualifier)) { - alias = qualifier; - } + beanDefinition.setPrimary(primary); - BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, - new String[] { alias }); - BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); + String qualifier = getQualifier(attributes); + if (StringUtils.hasText(qualifier)) { + alias = qualifier; + } - } - catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - } + BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, + new String[]{alias}); + BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); - /** - * Return the class used by {@link SpringFactoriesLoader} to load configuration - * candidates. - * @return the factory class - */ - private Class getSpringFactoriesLoaderFactoryClass() { - return PigxFeignAutoConfiguration.class; - } + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + } - private void validate(Map attributes) { - AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes); - // This blows up if an aliased property is overspecified - FeignClientsRegistrar.validateFallback(annotation.getClass("fallback")); - FeignClientsRegistrar.validateFallbackFactory(annotation.getClass("fallbackFactory")); - } - private String getName(Map attributes) { - String name = (String) attributes.get("serviceId"); - if (!StringUtils.hasText(name)) { - name = (String) attributes.get("name"); - } - if (!StringUtils.hasText(name)) { - name = (String) attributes.get("value"); - } - name = resolve(name); - return FeignClientsRegistrar.getName(name); - } + private void validate(Map attributes) { + AnnotationAttributes annotation = AnnotationAttributes.fromMap(attributes); + // This blows up if an aliased property is overspecified + FeignClientsRegistrar.validateFallback(annotation.getClass("fallback")); + FeignClientsRegistrar.validateFallbackFactory(annotation.getClass("fallbackFactory")); + } - private String getContextId(Map attributes) { - String contextId = (String) attributes.get("contextId"); - if (!StringUtils.hasText(contextId)) { - return getName(attributes); - } + private String getName(Map attributes) { + String name = (String) attributes.get("serviceId"); + if (!StringUtils.hasText(name)) { + name = (String) attributes.get("name"); + } + if (!StringUtils.hasText(name)) { + name = (String) attributes.get("value"); + } + name = resolve(name); + return FeignClientsRegistrar.getName(name); + } - contextId = resolve(contextId); - return FeignClientsRegistrar.getName(contextId); - } + private String getContextId(Map attributes) { + String contextId = (String) attributes.get("contextId"); + if (!StringUtils.hasText(contextId)) { + return getName(attributes); + } - private String resolve(String value) { - if (StringUtils.hasText(value)) { - return this.environment.resolvePlaceholders(value); - } - return value; - } + contextId = resolve(contextId); + return FeignClientsRegistrar.getName(contextId); + } - private String getUrl(Map attributes) { - // 如果是单体项目自动注入 & url 为空 - String url = (String) attributes.get("url"); - boolean present = ClassUtils.isPresent("com.alibaba.cloud.nacos.discovery.NacosDiscoveryClient", - this.getClass().getClassLoader()); - if (!StringUtils.hasText(url) && !present) { - url = resolve(BASE_URL); - } + private String resolve(String value) { + if (StringUtils.hasText(value)) { + return this.environment.resolvePlaceholders(value); + } + return value; + } - return FeignClientsRegistrar.getUrl(url); - } - private String getPath(Map attributes) { - String path = resolve((String) attributes.get("path")); - return FeignClientsRegistrar.getPath(path); - } + private String getUrl(Map attributes) { - @Nullable - private String getQualifier(@Nullable Map client) { - if (client == null) { - return null; - } - String qualifier = (String) client.get("qualifier"); - if (StringUtils.hasText(qualifier)) { - return qualifier; - } - return null; - } + // 如果是单体项目自动注入 & url 为空 + Boolean isMicro = environment.getProperty("spring.cloud.nacos.discovery.enabled", Boolean.class, true); - @Nullable - private String getClientName(@Nullable Map client) { - if (client == null) { - return null; - } - String value = (String) client.get("contextId"); - if (!StringUtils.hasText(value)) { - value = (String) client.get("value"); - } - if (!StringUtils.hasText(value)) { - value = (String) client.get("name"); - } - if (!StringUtils.hasText(value)) { - value = (String) client.get("serviceId"); - } - if (StringUtils.hasText(value)) { - return value; - } + if (isMicro) { + return null; + } - throw new IllegalStateException( - "Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName()); - } + Object objUrl = attributes.get("url"); - private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class); - builder.addConstructorArgValue(name); - builder.addConstructorArgValue(configuration); - registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), - builder.getBeanDefinition()); - } + String url = ""; + if (StringUtils.hasText(objUrl.toString())) { + url = resolve(objUrl.toString()); + } else { + url = resolve(BASE_URL); + } - private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className, - Object configuration) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class); - builder.addConstructorArgValue(name); - builder.addConstructorArgValue(className); - builder.addConstructorArgValue(configuration); - registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), - builder.getBeanDefinition()); - } + return FeignClientsRegistrar.getUrl(url); + } - @Override - public void setEnvironment(Environment environment) { - this.environment = environment; - } + private String getPath(Map attributes) { + String path = resolve((String) attributes.get("path")); + return FeignClientsRegistrar.getPath(path); + } + + @Nullable + private String getQualifier(@Nullable Map client) { + if (client == null) { + return null; + } + String qualifier = (String) client.get("qualifier"); + if (StringUtils.hasText(qualifier)) { + return qualifier; + } + return null; + } + + @Nullable + private String getClientName(@Nullable Map client) { + if (client == null) { + return null; + } + String value = (String) client.get("contextId"); + if (!StringUtils.hasText(value)) { + value = (String) client.get("value"); + } + if (!StringUtils.hasText(value)) { + value = (String) client.get("name"); + } + if (!StringUtils.hasText(value)) { + value = (String) client.get("serviceId"); + } + if (StringUtils.hasText(value)) { + return value; + } + + throw new IllegalStateException( + "Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName()); + } + + private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class); + builder.addConstructorArgValue(name); + builder.addConstructorArgValue(configuration); + registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), + builder.getBeanDefinition()); + } + + private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className, + Object configuration) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class); + builder.addConstructorArgValue(name); + builder.addConstructorArgValue(className); + builder.addConstructorArgValue(configuration); + registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), + builder.getBeanDefinition()); + } + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } } diff --git a/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/configuration/GlobalExceptionConfiguration.java b/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/configuration/GlobalExceptionConfiguration.java index 773d23c43..93b6726ee 100644 --- a/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/configuration/GlobalExceptionConfiguration.java +++ b/pigx-common/pigx-common-gateway/src/main/java/com/pig4cloud/pigx/common/gateway/configuration/GlobalExceptionConfiguration.java @@ -5,20 +5,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.pig4cloud.pigx.common.core.util.R; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import org.springframework.web.reactive.resource.NoResourceFoundException; /** * @author lengleng @@ -30,6 +26,7 @@ import org.springframework.web.reactive.resource.NoResourceFoundException; @Order(-1) @Configuration @RequiredArgsConstructor +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler { private final ObjectMapper objectMapper; @@ -62,24 +59,3 @@ public class GlobalExceptionConfiguration implements ErrorWebExceptionHandler { } } - - -/** - * 保持和低版本请求路径不存在的行为一致 - *

- * [Spring Boot - * 3.2.0] 404 Not Found behavior #38733 - */ -@Slf4j -@RestControllerAdvice -class ReactiveNoResourceFoundHandler { - - - @ExceptionHandler({NoResourceFoundException.class}) - @ResponseStatus(HttpStatus.NOT_FOUND) - public R noResourceFoundException(NoResourceFoundException exception) { - log.debug("请求路径 404 {}", exception.getMessage()); - return R.failed(exception.getMessage()); - } - -} diff --git a/pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/OpenAPIMetadataConfiguration.java b/pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/OpenAPIMetadataConfiguration.java index a73e2815b..ce2d488cd 100644 --- a/pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/OpenAPIMetadataConfiguration.java +++ b/pigx-common/pigx-common-swagger/src/main/java/com/pig4cloud/pigx/common/swagger/config/OpenAPIMetadataConfiguration.java @@ -20,6 +20,12 @@ public class OpenAPIMetadataConfiguration implements InitializingBean, Applicati @Override public void afterPropertiesSet() throws Exception { + String[] beanNamesForType = applicationContext.getBeanNamesForType(ServiceInstance.class); + + if (beanNamesForType.length == 0) { + return; + } + ServiceInstance serviceInstance = applicationContext.getBean(ServiceInstance.class); serviceInstance.getMetadata().put("spring-doc", path); } diff --git a/pigx-flow/pigx-flow-engine/pigx-flow-engine-biz/pom.xml b/pigx-flow/pigx-flow-engine/pigx-flow-engine-biz/pom.xml index efef84cc0..2e8b6656c 100644 --- a/pigx-flow/pigx-flow-engine/pigx-flow-engine-biz/pom.xml +++ b/pigx-flow/pigx-flow-engine/pigx-flow-engine-biz/pom.xml @@ -123,16 +123,34 @@ DmJdbcDriver18 - - - - org.springframework.boot - spring-boot-maven-plugin - - - io.fabric8 - docker-maven-plugin - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-flow/pigx-flow-task/pigx-flow-task-biz/pom.xml b/pigx-flow/pigx-flow-task/pigx-flow-task-biz/pom.xml index 39d49bfb6..6c93ece3a 100644 --- a/pigx-flow/pigx-flow-task/pigx-flow-task-biz/pom.xml +++ b/pigx-flow/pigx-flow-task/pigx-flow-task-biz/pom.xml @@ -103,16 +103,34 @@ DmJdbcDriver18 - - - - org.springframework.boot - spring-boot-maven-plugin - - - io.fabric8 - docker-maven-plugin - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-gateway/pom.xml b/pigx-gateway/pom.xml index b12d46f21..fec321844 100644 --- a/pigx-gateway/pom.xml +++ b/pigx-gateway/pom.xml @@ -66,18 +66,6 @@ com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config - - - io.springboot.plugin - spring-boot-starter-captcha - ${captcha.version} - - - - io.springboot.plugin - captcha-core - ${captcha.image.version} - org.springframework.boot diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/GatewayConfigProperties.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/GatewayConfigProperties.java deleted file mode 100644 index 23a4e8b13..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/GatewayConfigProperties.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.pig4cloud.pigx.gateway.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Component; - -/** - * @author lengleng - * @date 2020/10/2 - *

- * 网关通用配置文件 - */ -@Data -@Component -@RefreshScope -@ConfigurationProperties("gateway") -public class GatewayConfigProperties { - - /** - * 网关解密登录前端密码 秘钥 {@link com.pig4cloud.pigx.gateway.filter.PasswordDecoderFilter} - */ - public String encodeKey; - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java deleted file mode 100644 index 863ca4cb5..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/config/RouterFunctionConfiguration.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.gateway.config; - -import com.pig4cloud.pigx.gateway.handler.ImageCodeCheckHandler; -import com.pig4cloud.pigx.gateway.handler.ImageCodeCreateHandler; -import com.pig4cloud.pigx.gateway.handler.ImageCodeMathHandler; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.server.RequestPredicates; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; - -/** - * @author lengleng - * @date 2018/7/5 路由配置信息 - */ -@Slf4j -@Configuration -@AllArgsConstructor -public class RouterFunctionConfiguration { - - private final ImageCodeCheckHandler imageCodeCheckHandler; - - private final ImageCodeCreateHandler imageCodeCreateHandler; - - private final ImageCodeMathHandler imageCodeMathHandler; - - @Bean - public RouterFunction routerFunction() { - return RouterFunctions - .route(RequestPredicates.path("/code/create").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), - imageCodeCreateHandler) - .andRoute(RequestPredicates.path("/code/image").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), - imageCodeMathHandler) - .andRoute(RequestPredicates.POST("/code/check").and(RequestPredicates.accept(MediaType.ALL)), - imageCodeCheckHandler); - - } - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java deleted file mode 100644 index 43695920f..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/PasswordDecoderFilter.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.gateway.filter; - -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.Mode; -import cn.hutool.crypto.Padding; -import cn.hutool.crypto.SecureUtil; -import cn.hutool.crypto.symmetric.AES; -import cn.hutool.http.HttpUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.pig4cloud.pigx.common.core.constant.CacheConstants; -import com.pig4cloud.pigx.common.core.constant.CommonConstants; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import com.pig4cloud.pigx.common.core.constant.enums.EncFlagTypeEnum; -import com.pig4cloud.pigx.common.core.util.WebUtils; -import com.pig4cloud.pigx.gateway.config.GatewayConfigProperties; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage; -import org.springframework.cloud.gateway.support.BodyInserterContext; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.codec.HttpMessageReader; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpRequestDecorator; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.BodyInserter; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerStrategies; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.server.ServerWebExchange; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -/** - * @author lengleng - * @date 2020/1/8 密码解密工具类 - *

- * 参考 ModifyRequestBodyGatewayFilterFactory 实现 - */ -@Slf4j -@Component -@RequiredArgsConstructor -@SuppressWarnings("all") -public class PasswordDecoderFilter extends AbstractGatewayFilterFactory { - - private final List> messageReaders = HandlerStrategies.withDefaults().messageReaders(); - - private static final String PASSWORD = "password"; - - private static final String KEY_ALGORITHM = "AES"; - - private final StringRedisTemplate redisTemplate; - - private final GatewayConfigProperties gatewayConfig; - - static { - // 关闭hutool 强制关闭Bouncy Castle库的依赖 - SecureUtil.disableBouncyCastle(); - } - - @Override - public GatewayFilter apply(Object config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - // 1. 不是登录请求,直接向下执行 - if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL)) { - return chain.filter(exchange); - } - - // 2. 刷新token类型,直接向下执行 - String grantType = request.getQueryParams().getFirst("grant_type"); - if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) { - return chain.filter(exchange); - } - - // 3. 判断客户端是否需要解密,明文传输直接向下执行 - if (!isEncClient(request)) { - return chain.filter(exchange); - } - - // 4. 前端加密密文解密逻辑 - Class inClass = String.class; - Class outClass = String.class; - ServerRequest serverRequest = ServerRequest.create(exchange, messageReaders); - - // 解密生成新的报文 - Mono modifiedBody = serverRequest.bodyToMono(inClass).flatMap(decryptAES()); - - BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, outClass); - HttpHeaders headers = new HttpHeaders(); - headers.putAll(exchange.getRequest().getHeaders()); - headers.remove(HttpHeaders.CONTENT_LENGTH); - - headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); - CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers); - return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> { - ServerHttpRequest decorator = decorate(exchange, headers, outputMessage); - return chain.filter(exchange.mutate().request(decorator).build()); - })); - }; - } - - /** - * 根据请求的clientId 查询客户端配置是否是加密传输 - * @param request 请求上下文 - * @return true 加密传输 、 false 原文传输 - */ - private boolean isEncClient(ServerHttpRequest request) { - String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); - String clientId = WebUtils.extractClientId(header).orElse(null); - // 获取租户拼接区分租户的key - String tenantId = request.getHeaders().getFirst(CommonConstants.TENANT_ID); - String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId, - CacheConstants.CLIENT_FLAG, clientId); - - String val = redisTemplate.opsForValue().get(key); - - // 当配置不存在时,默认需要解密 - if (val == null) { - return true; - } - - JSONObject information = JSONUtil.parseObj(val); - if (StrUtil.equals(EncFlagTypeEnum.NO.getType(), information.getStr(CommonConstants.ENC_FLAG))) { - return false; - } - return true; - } - - /** - * 原文解密 - * @return - */ - private Function decryptAES() { - return s -> { - // 构建前端对应解密AES 因子 - AES aes = new AES(Mode.CFB, Padding.NoPadding, - new SecretKeySpec(gatewayConfig.getEncodeKey().getBytes(), KEY_ALGORITHM), - new IvParameterSpec(gatewayConfig.getEncodeKey().getBytes())); - - // 获取请求密码并解密 - Map inParamsMap = HttpUtil.decodeParamMap((String) s, CharsetUtil.CHARSET_UTF_8); - if (inParamsMap.containsKey(PASSWORD)) { - String password = aes.decryptStr(inParamsMap.get(PASSWORD)); - // 返回修改后报文字符 - inParamsMap.put(PASSWORD, password); - } - else { - log.error("非法请求数据:{}", s); - } - - // 使用 - return Mono.just(HttpUtil.toParams(inParamsMap, Charset.defaultCharset(), true)); - }; - } - - /** - * 报文转换 - * @return - */ - private ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, - CachedBodyOutputMessage outputMessage) { - return new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public HttpHeaders getHeaders() { - long contentLength = headers.getContentLength(); - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.putAll(super.getHeaders()); - if (contentLength > 0) { - httpHeaders.setContentLength(contentLength); - } - else { - httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); - } - return httpHeaders; - } - - @Override - public Flux getBody() { - return outputMessage.getBody(); - } - }; - } - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java deleted file mode 100644 index 79af25807..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/filter/ValidateCodeGatewayFilter.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.gateway.filter; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import com.anji.captcha.model.vo.CaptchaVO; -import com.anji.captcha.service.CaptchaService; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.pig4cloud.pigx.common.core.constant.CacheConstants; -import com.pig4cloud.pigx.common.core.constant.CommonConstants; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import com.pig4cloud.pigx.common.core.constant.enums.CaptchaFlagTypeEnum; -import com.pig4cloud.pigx.common.core.exception.ValidateCodeException; -import com.pig4cloud.pigx.common.core.util.R; -import com.pig4cloud.pigx.common.core.util.SpringContextHolder; -import com.pig4cloud.pigx.common.core.util.WebUtils; -import lombok.AllArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.gateway.filter.GatewayFilter; -import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; - -/** - * @author lengleng - * @date 2020/5/19 登录逻辑验证码处理 - */ -@Slf4j -@Component -@AllArgsConstructor -@SuppressWarnings("all") -public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory { - - private final StringRedisTemplate redisTemplate; - - private final ObjectMapper objectMapper; - - @Override - public GatewayFilter apply(Object config) { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - - // 不是登录请求直接向下执行 - if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL)) { - return chain.filter(exchange); - } - - // 刷新token,直接向下执行 - String grantType = request.getQueryParams().getFirst("grant_type"); - if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) { - return chain.filter(exchange); - } - - // mobile模式, 如果请求不包含mobile 参数直接 - String mobile = request.getQueryParams().getFirst(SecurityConstants.GRANT_MOBILE); - if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && StrUtil.isBlank(mobile)) { - throw new ValidateCodeException(); - } - - // mobile模式, 社交登录模式不校验验证码直接跳过 - if (StrUtil.equals(SecurityConstants.GRANT_MOBILE, grantType) && !StrUtil.contains(mobile, "SMS")) { - return chain.filter(exchange); - } - - // 判断客户端是否跳过检验 - if (!isCheckCaptchaClient(request)) { - return chain.filter(exchange); - } - - try { - // 校验验证码 - checkCode(request); - } - catch (Exception e) { - ServerHttpResponse response = exchange.getResponse(); - response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED); - try { - return response.writeWith(Mono - .just(response.bufferFactory().wrap(objectMapper.writeValueAsBytes(R.failed(e.getMessage()))))); - } - catch (JsonProcessingException e1) { - log.error("对象输出异常", e1); - } - } - - return chain.filter(exchange); - }; - } - - /** - * 是否需要校验客户端,根据client 查询客户端配置 - * @param request 请求 - * @return true 需要校验, false 不需要校验 - */ - private boolean isCheckCaptchaClient(ServerHttpRequest request) { - String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); - String clientId = WebUtils.extractClientId(header).orElse(null); - // 获取租户拼接区分租户的key - String tenantId = request.getHeaders().getFirst(CommonConstants.TENANT_ID); - String key = String.format("%s:%s:%s", StrUtil.isBlank(tenantId) ? CommonConstants.TENANT_ID_1 : tenantId, - CacheConstants.CLIENT_FLAG, clientId); - - String val = redisTemplate.opsForValue().get(key); - - // 当配置不存在时,不用校验 - if (val == null) { - return false; - } - - JSONObject information = JSONUtil.parseObj(val); - if (StrUtil.equals(CaptchaFlagTypeEnum.OFF.getType(), information.getStr(CommonConstants.CAPTCHA_FLAG))) { - return false; - } - return true; - } - - /** - * 检查code - * @param request - */ - @SneakyThrows - private void checkCode(ServerHttpRequest request) { - String code = request.getQueryParams().getFirst("code"); - - if (StrUtil.isBlank(code)) { - throw new ValidateCodeException("验证码不能为空"); - } - - String randomStr = request.getQueryParams().getFirst("randomStr"); - - // 若是滑块登录 - if (CommonConstants.IMAGE_CODE_TYPE.equalsIgnoreCase(randomStr)) { - CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); - CaptchaVO vo = new CaptchaVO(); - vo.setCaptchaVerification(code); - vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); - if (!captchaService.verification(vo).isSuccess()) { - throw new ValidateCodeException("验证码不能为空"); - } - return; - } - - // https://gitee.com/log4j/pig/issues/IWA0D - String mobile = request.getQueryParams().getFirst("mobile"); - if (StrUtil.isNotBlank(mobile)) { - randomStr = mobile; - } - - String key = CacheConstants.DEFAULT_CODE_KEY + randomStr; - if (!redisTemplate.hasKey(key)) { - throw new ValidateCodeException("验证码不合法"); - } - - String saveCode = redisTemplate.opsForValue().get(key); - - if (saveCode == null) { - throw new ValidateCodeException("验证码不合法"); - } - - if (StrUtil.isBlank(saveCode)) { - redisTemplate.delete(key); - throw new ValidateCodeException("验证码不合法"); - } - - if (!StrUtil.equals(saveCode, code)) { - redisTemplate.delete(key); - throw new ValidateCodeException("验证码不合法"); - } - - redisTemplate.delete(key); - } - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCheckHandler.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCheckHandler.java deleted file mode 100644 index aa4d37d70..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCheckHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.gateway.handler; - -import com.anji.captcha.model.common.ResponseModel; -import com.anji.captcha.model.vo.CaptchaVO; -import com.anji.captcha.service.CaptchaService; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.pig4cloud.pigx.common.core.constant.CommonConstants; -import com.pig4cloud.pigx.common.core.util.R; -import com.pig4cloud.pigx.common.core.util.SpringContextHolder; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerFunction; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; - -/** - * @author lengleng - * @date 2020/5/19 验证码生成逻辑处理类 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class ImageCodeCheckHandler implements HandlerFunction { - - private final ObjectMapper objectMapper; - - @Override - @SneakyThrows - public Mono handle(ServerRequest request) { - CaptchaVO vo = new CaptchaVO(); - vo.setPointJson(request.queryParam("pointJson").get()); - vo.setToken(request.queryParam("token").get()); - vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); - - CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); - ResponseModel responseModel = captchaService.check(vo); - - return ServerResponse.status(HttpStatus.OK) - .contentType(MediaType.APPLICATION_JSON) - .body(BodyInserters.fromValue(objectMapper.writeValueAsString(R.ok(responseModel)))); - } - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCreateHandler.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCreateHandler.java deleted file mode 100644 index a65a38a1b..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeCreateHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018-2025, lengleng All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * Neither the name of the pig4cloud.com developer nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * Author: lengleng (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.gateway.handler; - -import com.anji.captcha.model.common.ResponseModel; -import com.anji.captcha.model.vo.CaptchaVO; -import com.anji.captcha.service.CaptchaService; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.pig4cloud.pigx.common.core.constant.CommonConstants; -import com.pig4cloud.pigx.common.core.util.R; -import com.pig4cloud.pigx.common.core.util.SpringContextHolder; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerFunction; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; - -/** - * @author lengleng - * @date 2020/5/19 验证码生成逻辑处理类 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class ImageCodeCreateHandler implements HandlerFunction { - - private final ObjectMapper objectMapper; - - @Override - @SneakyThrows - public Mono handle(ServerRequest serverRequest) { - CaptchaVO vo = new CaptchaVO(); - vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE); - CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class); - ResponseModel responseModel = captchaService.get(vo); - - return ServerResponse.status(HttpStatus.OK) - .contentType(MediaType.APPLICATION_JSON) - .body(BodyInserters.fromValue(objectMapper.writeValueAsString(R.ok(responseModel)))); - } - -} diff --git a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeMathHandler.java b/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeMathHandler.java deleted file mode 100755 index 9d91c6ff2..000000000 --- a/pigx-gateway/src/main/java/com/pig4cloud/pigx/gateway/handler/ImageCodeMathHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pig4cloud.pigx.gateway.handler; - -import com.pig4cloud.pigx.common.core.constant.CacheConstants; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import io.springboot.captcha.ArithmeticCaptcha; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.util.FastByteArrayOutputStream; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.server.HandlerFunction; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Mono; - -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -/** - * @author lengleng - * @date 2023-09-29 数据验证码实现 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class ImageCodeMathHandler implements HandlerFunction { - - private static final Integer DEFAULT_IMAGE_WIDTH = 100; - - private static final Integer DEFAULT_IMAGE_HEIGHT = 40; - - private final StringRedisTemplate redisTemplate; - - @Override - public Mono handle(ServerRequest serverRequest) { - ArithmeticCaptcha captcha = new ArithmeticCaptcha(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT); - - String result = captcha.text(); - - // 保存验证码信息 - Optional randomStr = serverRequest.queryParam("randomStr"); - randomStr.ifPresent(s -> redisTemplate.opsForValue() - .set(CacheConstants.DEFAULT_CODE_KEY + s, result, SecurityConstants.CODE_TIME, TimeUnit.SECONDS)); - - // 转换流信息写出 - FastByteArrayOutputStream os = new FastByteArrayOutputStream(); - captcha.out(os); - - return ServerResponse.status(HttpStatus.OK) - .contentType(MediaType.IMAGE_JPEG) - .body(BodyInserters.fromResource(new ByteArrayResource(os.toByteArray()))); - } - -} diff --git a/pigx-gateway/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService b/pigx-gateway/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService deleted file mode 100644 index 742abee62..000000000 --- a/pigx-gateway/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService +++ /dev/null @@ -1 +0,0 @@ -com.pig4cloud.pigx.gateway.config.CaptchaCacheServiceProvider diff --git a/pigx-upms/pigx-upms-biz/pom.xml b/pigx-upms/pigx-upms-biz/pom.xml index fa60af007..cb1eeb2d3 100644 --- a/pigx-upms/pigx-upms-biz/pom.xml +++ b/pigx-upms/pigx-upms-biz/pom.xml @@ -161,37 +161,38 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin - CLASSIC + false - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - io.fabric8 - docker-maven-plugin - - false - - - + + + + + + + src/main/resources @@ -211,5 +212,4 @@ - diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/PigxAdminApplication.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/PigxAdminApplication.java index 0968550e3..3bbf726ca 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/PigxAdminApplication.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/PigxAdminApplication.java @@ -19,7 +19,6 @@ package com.pig4cloud.pigx.admin; -import com.pig4cloud.pigx.common.feign.annotation.EnablePigxFeignClients; import com.pig4cloud.pigx.common.security.annotation.EnablePigxResourceServer; import com.pig4cloud.pigx.common.swagger.annotation.EnableOpenApi; import org.springframework.boot.SpringApplication; @@ -33,7 +32,6 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; * 用户统一管理系统 */ @EnableOpenApi("admin") -@EnablePigxFeignClients @EnablePigxResourceServer @EnableDiscoveryClient @SpringBootApplication diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTokenController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTokenController.java index fe095d240..36564a00b 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTokenController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysTokenController.java @@ -39,7 +39,7 @@ import java.util.Map; */ @RestController @AllArgsConstructor -@RequestMapping("/token") +@RequestMapping("/sys-token") @Tag(description = "token", name = "令牌管理模块") @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) public class SysTokenController { diff --git a/pigx-upms/pigx-upms-biz/src/main/resources/logback-spring.xml b/pigx-upms/pigx-upms-biz/src/main/resources/logback-spring.xml index bacd3f9c6..3e292157f 100644 --- a/pigx-upms/pigx-upms-biz/src/main/resources/logback-spring.xml +++ b/pigx-upms/pigx-upms-biz/src/main/resources/logback-spring.xml @@ -60,7 +60,7 @@ - + diff --git a/pigx-visual/pigx-codegen/pom.xml b/pigx-visual/pigx-codegen/pom.xml index 3eee54cd1..538475067 100755 --- a/pigx-visual/pigx-codegen/pom.xml +++ b/pigx-visual/pigx-codegen/pom.xml @@ -175,26 +175,34 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - io.fabric8 - docker-maven-plugin - - false - - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/PigxCodeGenApplication.java b/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/PigxCodeGenApplication.java index 5d376d85b..3e0270d90 100755 --- a/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/PigxCodeGenApplication.java +++ b/pigx-visual/pigx-codegen/src/main/java/com/pig4cloud/pigx/codegen/PigxCodeGenApplication.java @@ -30,8 +30,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; * @date 2018/07/29 代码生成模块 */ @EnableDynamicDataSource -@EnableOpenApi("gen") @EnablePigxFeignClients +@EnableOpenApi("gen") @EnableDiscoveryClient @EnablePigxResourceServer @SpringBootApplication diff --git a/pigx-visual/pigx-daemon-quartz/pom.xml b/pigx-visual/pigx-daemon-quartz/pom.xml index 863fab1f9..5bc9521c6 100644 --- a/pigx-visual/pigx-daemon-quartz/pom.xml +++ b/pigx-visual/pigx-daemon-quartz/pom.xml @@ -99,21 +99,37 @@ org.springframework.boot spring-boot-starter-quartz + - - - - org.springframework.boot - spring-boot-maven-plugin - - - io.fabric8 - docker-maven-plugin - - false - - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-visual/pigx-mp-platform/pom.xml b/pigx-visual/pigx-mp-platform/pom.xml index cc1c12d83..c71ab420a 100755 --- a/pigx-visual/pigx-mp-platform/pom.xml +++ b/pigx-visual/pigx-mp-platform/pom.xml @@ -115,26 +115,34 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - io.fabric8 - docker-maven-plugin - - false - - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java index c654dd614..ee9acdafd 100644 --- a/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java +++ b/pigx-visual/pigx-mp-platform/src/main/java/com/pig4cloud/pigx/mp/config/WxMpInitConfigRunner.java @@ -15,7 +15,7 @@ import me.chanjar.weixin.mp.api.WxMpMessageRouter; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; import me.chanjar.weixin.mp.constant.WxMpEventConstants; -import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; @@ -88,7 +88,7 @@ public class WxMpInitConfigRunner { @Async @Order - @EventListener({ WebServerInitializedEvent.class }) + @EventListener({ ApplicationReadyEvent.class }) public void WebServerInit() { this.initServices(); } diff --git a/pigx-visual/pigx-pay-platform/pom.xml b/pigx-visual/pigx-pay-platform/pom.xml index 536c5d11f..b24da75b6 100755 --- a/pigx-visual/pigx-pay-platform/pom.xml +++ b/pigx-visual/pigx-pay-platform/pom.xml @@ -141,33 +141,34 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - true - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - io.fabric8 - docker-maven-plugin - - false - - - - + + + cloud + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + CLASSIC + + + + + + io.fabric8 + docker-maven-plugin + + false + + + + + + diff --git a/pom.xml b/pom.xml index 16bc9164b..5fceece20 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 7.0.0 2.0.0 3.0.0 - 2.0.9 + 3.0.5 2.3 3.1 3.0.5 @@ -252,45 +252,9 @@ - - - - rdc-releases - https://packages.aliyun.com/maven/repository/2161442-release-DcBZC1/ - - - rdc-snapshots - https://packages.aliyun.com/maven/repository/2161442-snapshot-FzKqZK/ - - - - - - public - aliyun nexus - https://maven.aliyun.com/repository/public/ - - true - - - - - - - aliyun-plugin - https://maven.aliyun.com/repository/public - - true - - - false - - - - - dev + cloud dev @@ -302,6 +266,12 @@ true + + boot + + pigx-boot + +