diff --git a/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java b/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java index 3da3caeb0..8e2945c5f 100644 --- a/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java +++ b/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java @@ -19,12 +19,21 @@ import org.springframework.stereotype.Service; import java.time.Instant; import java.util.List; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** 将已经通过国内 HMAC 与 Redis 校验的会话兑换为海外 RS256 短时令牌。 */ @Service @ConditionalOnProperty(name = "baiyue.security.overseas-jwt.enabled", havingValue = "true") public class OverseasTokenService { + private static final List OVERSEAS_AUTHORITY_PREFIXES = List.of( + "platform:overseas-warehouse:", + "platform:overseas-business:", + "platform:overseas-master-data:", + "lastleg:" + ); + @Resource private AuthAccountRepository accounts; @Resource private AuthorizationLoader authorizationLoader; @Resource private OverseasJwtProperties properties; @@ -50,7 +59,7 @@ public class OverseasTokenService { .claim("membership_id", authorization.getMembershipId()) .claim("app_code", authorization.getAppCode()).claim("client_type", authorization.getClientType()) .claim("roles", authorization.getRoles()) - .claim("authorities", authorization.getPermissions()) + .claim("authorities", overseasAuthorities(authorization.getPermissions())) .claim("permission_version", authorization.getPermissionVersion() == null ? 0L : authorization.getPermissionVersion()) .build(); String token = encoder.encode(JwtEncoderParameters.from( @@ -58,5 +67,12 @@ public class OverseasTokenService { return new OverseasTokenResponse("Bearer", token, properties.accessTokenTtl().toSeconds()); } + private Set overseasAuthorities(Set permissions) { + if (permissions == null || permissions.isEmpty()) return Set.of(); + return permissions.stream() + .filter(permission -> permission != null && OVERSEAS_AUTHORITY_PREFIXES.stream().anyMatch(permission::startsWith)) + .collect(Collectors.toUnmodifiableSet()); + } + public record OverseasTokenResponse(String tokenType, String accessToken, long expiresIn) { } } diff --git a/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java b/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java index 642adfe56..20fd26464 100644 --- a/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java +++ b/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java @@ -48,8 +48,10 @@ class OverseasTokenServiceTest { account.setId(42L); account.setAccountStatus("ACTIVE"); account.setDefaultTenantId(999L); account.setDefaultMembershipId(84L); account.setDefaultAppCode("MERCHANT"); String authority = "platform:overseas-master-data:quote:list"; + String lastlegAuthority = "lastleg:pda:operate"; + String domesticAuthority = "platform:firstleg:order:list"; AuthorizationSnapshot snapshot = new AuthorizationSnapshot(42L, 0L, 84L, "PLATFORM", "WEB", - Set.of("PLATFORM_ADMIN"), Set.of(authority), 7L); + Set.of("PLATFORM_ADMIN"), Set.of(authority, lastlegAuthority, domesticAuthority), 7L); Jwt encoded = org.mockito.Mockito.mock(Jwt.class); when(accounts.findById(42L)).thenReturn(account); when(authorizationLoader.load(account)).thenReturn(snapshot); @@ -70,7 +72,7 @@ class OverseasTokenServiceTest { .containsEntry("app_code", "PLATFORM").containsEntry("client_type", "WEB") .containsEntry("permission_version", 7L) .containsEntry("roles", Set.of("PLATFORM_ADMIN")) - .containsEntry("authorities", Set.of(authority)) + .containsEntry("authorities", Set.of(authority, lastlegAuthority)) .doesNotContainKeys("userId", "tenantId", "appCode", "permissionVersion"); assertThat(response.expiresIn()).isEqualTo(900); }