From 993879a6c3d9f863b8cb5e6adb3db4fb7537bdf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B7=E5=86=B7?= <2270033969@qq.com> Date: Sat, 1 Jun 2024 12:29:24 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20add=20=20NoToken=20Feign=20?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E8=87=AA=E5=8A=A8=E7=BB=B4=E6=8A=A4header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pig/auth/endpoint/PigTokenEndpoint.java | 3 +- .../feign/PigFeignAutoConfiguration.java | 62 ++++--- .../pig/common/feign/annotation/NoToken.java | 15 ++ .../core/PigFeignInnerRequestInterceptor.java | 34 ++++ .../pig/common/log/event/SysLogListener.java | 63 ++++--- .../service/PigAppUserDetailsServiceImpl.java | 2 +- .../PigRemoteRegisteredClientRepository.java | 163 +++++++++--------- .../service/PigUserDetailsServiceImpl.java | 56 +++--- pig-upms/pig-upms-api/pom.xml | 5 +- .../api/feign/RemoteClientDetailsService.java | 21 ++- .../pig/admin/api/feign/RemoteLogService.java | 9 +- .../admin/api/feign/RemoteParamService.java | 20 +-- .../admin/api/feign/RemoteTokenService.java | 56 +++--- .../admin/api/feign/RemoteUserService.java | 32 ++-- .../pig/admin/api/util/ParamResolver.java | 3 +- .../admin/controller/SysTokenController.java | 5 +- .../admin/controller/SysUserController.java | 1 - .../service/impl/SysUserServiceImpl.java | 6 +- 18 files changed, 299 insertions(+), 257 deletions(-) create mode 100644 pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/annotation/NoToken.java create mode 100644 pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/core/PigFeignInnerRequestInterceptor.java diff --git a/pig-auth/src/main/java/com/pig4cloud/pig/auth/endpoint/PigTokenEndpoint.java b/pig-auth/src/main/java/com/pig4cloud/pig/auth/endpoint/PigTokenEndpoint.java index f420e92a..b74a9ec7 100644 --- a/pig-auth/src/main/java/com/pig4cloud/pig/auth/endpoint/PigTokenEndpoint.java +++ b/pig-auth/src/main/java/com/pig4cloud/pig/auth/endpoint/PigTokenEndpoint.java @@ -27,7 +27,6 @@ import com.pig4cloud.pig.admin.api.vo.TokenVo; import com.pig4cloud.pig.auth.support.handler.PigAuthenticationFailureEventHandler; import com.pig4cloud.pig.common.core.constant.CacheConstants; import com.pig4cloud.pig.common.core.constant.CommonConstants; -import com.pig4cloud.pig.common.core.constant.SecurityConstants; import com.pig4cloud.pig.common.core.util.R; import com.pig4cloud.pig.common.core.util.RetOps; import com.pig4cloud.pig.common.core.util.SpringContextHolder; @@ -109,7 +108,7 @@ public class PigTokenEndpoint { @RequestParam(OAuth2ParameterNames.SCOPE) String scope, @RequestParam(OAuth2ParameterNames.STATE) String state) { SysOauthClientDetails clientDetails = RetOps - .of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN)) + .of(clientDetailsService.getClientDetailsById(clientId)) .getData() .orElseThrow(() -> new OAuthClientException("clientId 不合法")); diff --git a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/PigFeignAutoConfiguration.java b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/PigFeignAutoConfiguration.java index 82d3fa39..a417a9ac 100755 --- a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/PigFeignAutoConfiguration.java +++ b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/PigFeignAutoConfiguration.java @@ -20,6 +20,7 @@ import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration; import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser; import com.fasterxml.jackson.databind.ObjectMapper; +import com.pig4cloud.pig.common.feign.core.PigFeignInnerRequestInterceptor; import com.pig4cloud.pig.common.feign.core.PigFeignRequestCloseInterceptor; import com.pig4cloud.pig.common.feign.sentinel.ext.PigSentinelFeign; import com.pig4cloud.pig.common.feign.sentinel.handle.PigUrlBlockHandler; @@ -45,33 +46,44 @@ import org.springframework.context.annotation.Scope; @AutoConfigureBefore(SentinelFeignAutoConfiguration.class) public class PigFeignAutoConfiguration { - @Bean - @Scope("prototype") - @ConditionalOnMissingBean - @ConditionalOnProperty(name = "feign.sentinel.enabled") - public Feign.Builder feignSentinelBuilder() { - return PigSentinelFeign.builder(); - } + @Bean + @Scope("prototype") + @ConditionalOnMissingBean + @ConditionalOnProperty(name = "feign.sentinel.enabled") + public Feign.Builder feignSentinelBuilder() { + return PigSentinelFeign.builder(); + } - @Bean - @ConditionalOnMissingBean - public BlockExceptionHandler blockExceptionHandler(ObjectMapper objectMapper) { - return new PigUrlBlockHandler(objectMapper); - } + @Bean + @ConditionalOnMissingBean + public BlockExceptionHandler blockExceptionHandler(ObjectMapper objectMapper) { + return new PigUrlBlockHandler(objectMapper); + } - @Bean - @ConditionalOnMissingBean - public RequestOriginParser requestOriginParser() { - return new PigHeaderRequestOriginParser(); - } + @Bean + @ConditionalOnMissingBean + public RequestOriginParser requestOriginParser() { + return new PigHeaderRequestOriginParser(); + } - /** - * add http connection close header - * @return - */ - @Bean - public PigFeignRequestCloseInterceptor pigFeignRequestCloseInterceptor() { - return new PigFeignRequestCloseInterceptor(); - } + /** + * add http connection close header + * + * @return + */ + @Bean + public PigFeignRequestCloseInterceptor pigFeignRequestCloseInterceptor() { + return new PigFeignRequestCloseInterceptor(); + } + + /** + * add inner request header + * + * @return PigFeignInnerRequestInterceptor + */ + @Bean + public PigFeignInnerRequestInterceptor pigFeignInnerRequestInterceptor() { + return new PigFeignInnerRequestInterceptor(); + } } diff --git a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/annotation/NoToken.java b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/annotation/NoToken.java new file mode 100644 index 00000000..ba946af4 --- /dev/null +++ b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/annotation/NoToken.java @@ -0,0 +1,15 @@ +package com.pig4cloud.pig.common.feign.annotation; + +import java.lang.annotation.*; + +/** + * 服务无token调用声明注解 + *
+ * 只有发起方没有 token 时候才需要添加此注解, @NoToken + @Inner + *
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface NoToken {
+}
diff --git a/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/core/PigFeignInnerRequestInterceptor.java b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/core/PigFeignInnerRequestInterceptor.java
new file mode 100644
index 00000000..f4181291
--- /dev/null
+++ b/pig-common/pig-common-feign/src/main/java/com/pig4cloud/pig/common/feign/core/PigFeignInnerRequestInterceptor.java
@@ -0,0 +1,34 @@
+package com.pig4cloud.pig.common.feign.core;
+
+import com.pig4cloud.pig.common.core.constant.SecurityConstants;
+import com.pig4cloud.pig.common.feign.annotation.NoToken;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.core.Ordered;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author lengleng
+ * @date 2024/6/1
+ */
+public class PigFeignInnerRequestInterceptor implements RequestInterceptor, Ordered {
+ /**
+ * Called for every request. Add data using methods on the supplied {@link RequestTemplate}.
+ *
+ * @param template
+ */
+ @Override
+ public void apply(RequestTemplate template) {
+ Method method = template.methodMetadata().method();
+ NoToken noToken = method.getAnnotation(NoToken.class);
+ if (noToken != null) {
+ template.header(SecurityConstants.FROM, SecurityConstants.FROM_IN);
+ }
+ }
+
+ @Override
+ public int getOrder() {
+ return Integer.MIN_VALUE;
+ }
+}
diff --git a/pig-common/pig-common-log/src/main/java/com/pig4cloud/pig/common/log/event/SysLogListener.java b/pig-common/pig-common-log/src/main/java/com/pig4cloud/pig/common/log/event/SysLogListener.java
index 581db9c5..7fb2df31 100755
--- a/pig-common/pig-common-log/src/main/java/com/pig4cloud/pig/common/log/event/SysLogListener.java
+++ b/pig-common/pig-common-log/src/main/java/com/pig4cloud/pig/common/log/event/SysLogListener.java
@@ -24,7 +24,6 @@ import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.pig4cloud.pig.admin.api.entity.SysLog;
import com.pig4cloud.pig.admin.api.feign.RemoteLogService;
-import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.jackson.PigJavaTimeModule;
import com.pig4cloud.pig.common.log.config.PigLogProperties;
import lombok.RequiredArgsConstructor;
@@ -45,45 +44,45 @@ import java.util.Objects;
@RequiredArgsConstructor
public class SysLogListener implements InitializingBean {
- // new 一个 避免日志脱敏策略影响全局ObjectMapper
- private final static ObjectMapper objectMapper = new ObjectMapper();
+ // new 一个 避免日志脱敏策略影响全局ObjectMapper
+ private final static ObjectMapper objectMapper = new ObjectMapper();
- private final RemoteLogService remoteLogService;
+ private final RemoteLogService remoteLogService;
- private final PigLogProperties logProperties;
+ private final PigLogProperties logProperties;
- @SneakyThrows
- @Async
- @Order
- @EventListener(SysLogEvent.class)
- public void saveSysLog(SysLogEvent event) {
- SysLogEventSource source = (SysLogEventSource) event.getSource();
- SysLog sysLog = new SysLog();
- BeanUtils.copyProperties(source, sysLog);
+ @SneakyThrows
+ @Async
+ @Order
+ @EventListener(SysLogEvent.class)
+ public void saveSysLog(SysLogEvent event) {
+ SysLogEventSource source = (SysLogEventSource) event.getSource();
+ SysLog sysLog = new SysLog();
+ BeanUtils.copyProperties(source, sysLog);
- // json 格式刷参数放在异步中处理,提升性能
- if (Objects.nonNull(source.getBody())) {
- String params = objectMapper.writeValueAsString(source.getBody());
- sysLog.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
- }
+ // json 格式刷参数放在异步中处理,提升性能
+ if (Objects.nonNull(source.getBody())) {
+ String params = objectMapper.writeValueAsString(source.getBody());
+ sysLog.setParams(StrUtil.subPre(params, logProperties.getMaxLength()));
+ }
- remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN);
- }
+ remoteLogService.saveLog(sysLog);
+ }
- @Override
- public void afterPropertiesSet() {
- objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
- String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);
+ @Override
+ public void afterPropertiesSet() {
+ objectMapper.addMixIn(Object.class, PropertyFilterMixIn.class);
+ String[] ignorableFieldNames = logProperties.getExcludeFields().toArray(new String[0]);
- FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
- SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
- objectMapper.setFilterProvider(filters);
- objectMapper.registerModule(new PigJavaTimeModule());
- }
+ FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name",
+ SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
+ objectMapper.setFilterProvider(filters);
+ objectMapper.registerModule(new PigJavaTimeModule());
+ }
- @JsonFilter("filter properties by name")
- class PropertyFilterMixIn {
+ @JsonFilter("filter properties by name")
+ class PropertyFilterMixIn {
- }
+ }
}
diff --git a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigAppUserDetailsServiceImpl.java b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigAppUserDetailsServiceImpl.java
index 93a718af..9875968d 100755
--- a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigAppUserDetailsServiceImpl.java
+++ b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigAppUserDetailsServiceImpl.java
@@ -57,7 +57,7 @@ public class PigAppUserDetailsServiceImpl implements PigUserDetailsService {
UserDTO userDTO = new UserDTO();
userDTO.setPhone(phone);
- R
- * IMPORTANT: Sensitive information should be encoded externally from the
- * implementation, e.g. {@link RegisteredClient#getClientSecret()}
- * @param registeredClient the {@link RegisteredClient}
- */
- @Override
- public void save(RegisteredClient registeredClient) {
- }
+ /**
+ * Saves the registered client.
+ *
+ *
+ * IMPORTANT: Sensitive information should be encoded externally from the
+ * implementation, e.g. {@link RegisteredClient#getClientSecret()}
+ *
+ * @param registeredClient the {@link RegisteredClient}
+ */
+ @Override
+ public void save(RegisteredClient registeredClient) {
+ }
- /**
- * Returns the registered client identified by the provided {@code id}, or
- * {@code null} if not found.
- * @param id the registration identifier
- * @return the {@link RegisteredClient} if found, otherwise {@code null}
- */
- @Override
- public RegisteredClient findById(String id) {
- throw new UnsupportedOperationException();
- }
+ /**
+ * Returns the registered client identified by the provided {@code id}, or
+ * {@code null} if not found.
+ *
+ * @param id the registration identifier
+ * @return the {@link RegisteredClient} if found, otherwise {@code null}
+ */
+ @Override
+ public RegisteredClient findById(String id) {
+ throw new UnsupportedOperationException();
+ }
- /**
- * Returns the registered client identified by the provided {@code clientId}, or
- * {@code null} if not found.
- * @param clientId the client identifier
- * @return the {@link RegisteredClient} if found, otherwise {@code null}
- */
+ /**
+ * Returns the registered client identified by the provided {@code clientId}, or
+ * {@code null} if not found.
+ * @param clientId the client identifier
+ * @return the {@link RegisteredClient} if found, otherwise {@code null}
+ */
- /**
- * 重写原生方法支持redis缓存
- * @param clientId
- * @return
- */
- @Override
- @SneakyThrows
- @Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
- public RegisteredClient findByClientId(String clientId) {
+ /**
+ * 重写原生方法支持redis缓存
+ *
+ * @param clientId
+ * @return
+ */
+ @Override
+ @SneakyThrows
+ @Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null")
+ public RegisteredClient findByClientId(String clientId) {
- SysOauthClientDetails clientDetails = RetOps
- .of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN))
- .getData()
- .orElseThrow(() -> new OAuth2AuthorizationCodeRequestAuthenticationException(
- new OAuth2Error("客户端查询异常,请检查数据库链接"), null));
+ SysOauthClientDetails clientDetails = RetOps
+ .of(clientDetailsService.getClientDetailsById(clientId))
+ .getData()
+ .orElseThrow(() -> new OAuth2AuthorizationCodeRequestAuthenticationException(
+ new OAuth2Error("客户端查询异常,请检查数据库链接"), null));
- RegisteredClient.Builder builder = RegisteredClient.withId(clientDetails.getClientId())
- .clientId(clientDetails.getClientId())
- .clientSecret(SecurityConstants.NOOP + clientDetails.getClientSecret())
- .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
+ RegisteredClient.Builder builder = RegisteredClient.withId(clientDetails.getClientId())
+ .clientId(clientDetails.getClientId())
+ .clientSecret(SecurityConstants.NOOP + clientDetails.getClientSecret())
+ .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC);
- for (String authorizedGrantType : clientDetails.getAuthorizedGrantTypes()) {
- builder.authorizationGrantType(new AuthorizationGrantType(authorizedGrantType));
+ for (String authorizedGrantType : clientDetails.getAuthorizedGrantTypes()) {
+ builder.authorizationGrantType(new AuthorizationGrantType(authorizedGrantType));
- }
- // 回调地址
- Optional.ofNullable(clientDetails.getWebServerRedirectUri())
- .ifPresent(redirectUri -> Arrays.stream(redirectUri.split(StrUtil.COMMA))
- .filter(StrUtil::isNotBlank)
- .forEach(builder::redirectUri));
+ }
+ // 回调地址
+ Optional.ofNullable(clientDetails.getWebServerRedirectUri())
+ .ifPresent(redirectUri -> Arrays.stream(redirectUri.split(StrUtil.COMMA))
+ .filter(StrUtil::isNotBlank)
+ .forEach(builder::redirectUri));
- // scope
- Optional.ofNullable(clientDetails.getScope())
- .ifPresent(scope -> Arrays.stream(scope.split(StrUtil.COMMA))
- .filter(StrUtil::isNotBlank)
- .forEach(builder::scope));
+ // scope
+ Optional.ofNullable(clientDetails.getScope())
+ .ifPresent(scope -> Arrays.stream(scope.split(StrUtil.COMMA))
+ .filter(StrUtil::isNotBlank)
+ .forEach(builder::scope));
- return builder
- .tokenSettings(TokenSettings.builder()
- .accessTokenFormat(OAuth2TokenFormat.REFERENCE)
- .accessTokenTimeToLive(Duration.ofSeconds(
- Optional.ofNullable(clientDetails.getAccessTokenValidity()).orElse(accessTokenValiditySeconds)))
- .refreshTokenTimeToLive(Duration.ofSeconds(Optional.ofNullable(clientDetails.getRefreshTokenValidity())
- .orElse(refreshTokenValiditySeconds)))
- .build())
- .clientSettings(ClientSettings.builder()
- .requireAuthorizationConsent(!BooleanUtil.toBoolean(clientDetails.getAutoapprove()))
- .build())
- .build();
+ return builder
+ .tokenSettings(TokenSettings.builder()
+ .accessTokenFormat(OAuth2TokenFormat.REFERENCE)
+ .accessTokenTimeToLive(Duration.ofSeconds(
+ Optional.ofNullable(clientDetails.getAccessTokenValidity()).orElse(accessTokenValiditySeconds)))
+ .refreshTokenTimeToLive(Duration.ofSeconds(Optional.ofNullable(clientDetails.getRefreshTokenValidity())
+ .orElse(refreshTokenValiditySeconds)))
+ .build())
+ .clientSettings(ClientSettings.builder()
+ .requireAuthorizationConsent(!BooleanUtil.toBoolean(clientDetails.getAutoapprove()))
+ .build())
+ .build();
- }
+ }
}
diff --git a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java
index a997a928..a31a9231 100755
--- a/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java
+++ b/pig-common/pig-common-security/src/main/java/com/pig4cloud/pig/common/security/service/PigUserDetailsServiceImpl.java
@@ -20,7 +20,6 @@ import com.pig4cloud.pig.admin.api.dto.UserDTO;
import com.pig4cloud.pig.admin.api.dto.UserInfo;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
-import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@@ -40,36 +39,37 @@ import org.springframework.security.core.userdetails.UserDetails;
@RequiredArgsConstructor
public class PigUserDetailsServiceImpl implements PigUserDetailsService {
- private final RemoteUserService remoteUserService;
+ private final RemoteUserService remoteUserService;
- private final CacheManager cacheManager;
+ private final CacheManager cacheManager;
- /**
- * 用户名密码登录
- * @param username 用户名
- * @return
- */
- @Override
- @SneakyThrows
- public UserDetails loadUserByUsername(String username) {
- Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
- if (cache != null && cache.get(username) != null) {
- return (PigUser) cache.get(username).get();
- }
+ /**
+ * 用户名密码登录
+ *
+ * @param username 用户名
+ * @return
+ */
+ @Override
+ @SneakyThrows
+ public UserDetails loadUserByUsername(String username) {
+ Cache cache = cacheManager.getCache(CacheConstants.USER_DETAILS);
+ if (cache != null && cache.get(username) != null) {
+ return (PigUser) cache.get(username).get();
+ }
- UserDTO userDTO = new UserDTO();
- userDTO.setUsername(username);
- R