From a25963323b9fde60d0c22a8c344c7d5be3a6bc50 Mon Sep 17 00:00:00 2001 From: PIGCLOUD Date: Tue, 4 Nov 2025 11:03:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(security):=20=E5=A2=9E=E5=BC=BAOAuth2=20to?= =?UTF-8?q?ken=E9=AA=8C=E8=AF=81=E7=9A=84=E7=94=A8=E6=88=B7=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在PigxCustomOpaqueTokenIntrospector中增加用户账号状态检查逻辑 - 当用户账号被锁定或过期时拒绝访问并抛出InvalidBearerTokenException - 完善账号异常状态的日志记录和错误处理机制 - 保持原有客户端信息注入功能不变 --- .../PigxCustomOpaqueTokenIntrospector.java | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxCustomOpaqueTokenIntrospector.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxCustomOpaqueTokenIntrospector.java index 694199e32..16128fc00 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxCustomOpaqueTokenIntrospector.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxCustomOpaqueTokenIntrospector.java @@ -33,52 +33,67 @@ import java.util.Optional; @RequiredArgsConstructor public class PigxCustomOpaqueTokenIntrospector implements OpaqueTokenIntrospector { - private final OAuth2AuthorizationService authorizationService; + private final OAuth2AuthorizationService authorizationService; - @Override - public OAuth2AuthenticatedPrincipal introspect(String token) { - OAuth2Authorization oldAuthorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); - if (Objects.isNull(oldAuthorization)) { - throw new InvalidBearerTokenException(token); - } + @Override + public OAuth2AuthenticatedPrincipal introspect(String token) { + OAuth2Authorization oldAuthorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (Objects.isNull(oldAuthorization)) { + throw new InvalidBearerTokenException(token); + } - // 客户端模式默认返回 - if (AuthorizationGrantType.CLIENT_CREDENTIALS.equals(oldAuthorization.getAuthorizationGrantType())) { - return new PigxClientCredentialsOAuth2AuthenticatedPrincipal( - Objects.requireNonNull(oldAuthorization.getAccessToken().getClaims()), - AuthorityUtils.NO_AUTHORITIES, oldAuthorization.getPrincipalName()); - } + // 客户端模式默认返回 + if (AuthorizationGrantType.CLIENT_CREDENTIALS.equals(oldAuthorization.getAuthorizationGrantType())) { + return new PigxClientCredentialsOAuth2AuthenticatedPrincipal( + Objects.requireNonNull(oldAuthorization.getAccessToken().getClaims()), + AuthorityUtils.NO_AUTHORITIES, oldAuthorization.getPrincipalName()); + } - Map userDetailsServiceMap = SpringContextHolder - .getBeansOfType(PigxUserDetailsService.class); + Map userDetailsServiceMap = SpringContextHolder + .getBeansOfType(PigxUserDetailsService.class); - Optional optional = userDetailsServiceMap.values() - .stream() - .filter(service -> service.support(Objects.requireNonNull(oldAuthorization).getRegisteredClientId(), - oldAuthorization.getAuthorizationGrantType().getValue())) - .max(Comparator.comparingInt(Ordered::getOrder)); + Optional optional = userDetailsServiceMap.values() + .stream() + .filter(service -> service.support(Objects.requireNonNull(oldAuthorization).getRegisteredClientId(), + oldAuthorization.getAuthorizationGrantType().getValue())) + .max(Comparator.comparingInt(Ordered::getOrder)); - UserDetails userDetails = null; - try { - Object principal = Objects.requireNonNull(oldAuthorization).getAttributes().get(Principal.class.getName()); - UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) principal; - Object tokenPrincipal = usernamePasswordAuthenticationToken.getPrincipal(); - userDetails = optional.get().loadUserByUser((PigxUser) tokenPrincipal); - } - catch (UsernameNotFoundException notFoundException) { - log.warn("用户不不存在 {}", notFoundException.getLocalizedMessage()); - throw notFoundException; - } - catch (Exception ex) { - log.error("资源服务器 introspect Token error {}", ex.getLocalizedMessage()); - } + UserDetails userDetails = null; + try { + Object principal = Objects.requireNonNull(oldAuthorization).getAttributes().get(Principal.class.getName()); + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) principal; + Object tokenPrincipal = usernamePasswordAuthenticationToken.getPrincipal(); + userDetails = optional.get().loadUserByUser((PigxUser) tokenPrincipal); + } catch (UsernameNotFoundException notFoundException) { + log.warn("用户不不存在 {}", notFoundException.getLocalizedMessage()); + throw notFoundException; + } catch (Exception ex) { + log.error("资源服务器 introspect Token error {}", ex.getLocalizedMessage()); + } - // 注入客户端信息,方便上下文中获取 - PigxUser pigxUser = (PigxUser) userDetails; - Objects.requireNonNull(pigxUser) - .getAttributes() - .put(SecurityConstants.CLIENT_ID, oldAuthorization.getRegisteredClientId()); - return pigxUser; - } + // 检查用户账号状态 + if (Objects.nonNull(userDetails)) { + boolean isLocked = !userDetails.isAccountNonLocked(); + boolean isExpired = !userDetails.isAccountNonExpired(); + + if (isLocked) { + log.warn("用户账号 {} 已被锁定,拒绝访问", userDetails.getUsername()); + throw new InvalidBearerTokenException(token); + } + + if (isExpired) { + log.warn("用户账号 {} 已过期,拒绝访问", userDetails.getUsername()); + throw new InvalidBearerTokenException(token); + } + } + + // 注入客户端信息,方便上下文中获取 + PigxUser pigxUser = (PigxUser) userDetails; + + Objects.requireNonNull(pigxUser) + .getAttributes() + .put(SecurityConstants.CLIENT_ID, oldAuthorization.getRegisteredClientId()); + return pigxUser; + } }