From a077f828aedefa9e06248adf1888486502327983 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 7 Sep 2026 12:14:48 +0800 Subject: [PATCH] feat: return authorization snapshot outside jwt --- .../main/java/com/baiyue/auth/dto/TokenResponse.java | 10 +++++++++- .../java/com/baiyue/auth/service/AuthService.java | 3 ++- .../com/baiyue/auth/service/OverseasTokenService.java | 11 +++++++++-- .../baiyue/auth/service/AuthServiceSmallJwtTest.java | 10 ++++++++-- .../baiyue/auth/service/OverseasTokenServiceTest.java | 3 +++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/auth/src/main/java/com/baiyue/auth/dto/TokenResponse.java b/auth/src/main/java/com/baiyue/auth/dto/TokenResponse.java index ac2206a4d..aa86d983c 100644 --- a/auth/src/main/java/com/baiyue/auth/dto/TokenResponse.java +++ b/auth/src/main/java/com/baiyue/auth/dto/TokenResponse.java @@ -2,6 +2,8 @@ package com.baiyue.auth.dto; import io.swagger.v3.oas.annotations.media.Schema; +import java.util.Set; + /** * 认证令牌响应契约,返回访问令牌、刷新令牌及其有效期等会话信息。 */ @@ -15,6 +17,12 @@ public record TokenResponse( @Schema(description = "Short-lived overseas API access token; null only when overseas JWT is disabled / 海外 API 短时访问令牌;仅海外 JWT 未启用时为空", format = "password", nullable = true) String overseasAccessToken, @Schema(description = "Overseas access token lifetime in seconds; zero only when overseas JWT is disabled / 海外访问令牌有效秒数;仅海外 JWT 未启用时为 0", - example = "900", minimum = "0") long overseasExpiresIn + example = "900", minimum = "0") long overseasExpiresIn, + @Schema(description = "Current role snapshot returned outside JWT / JWT 外返回的当前角色快照") Set roles, + @Schema(description = "Current authority snapshot returned outside JWT / JWT 外返回的当前权限快照") Set authorities ) { + public TokenResponse { + roles = roles == null ? Set.of() : Set.copyOf(roles); + authorities = authorities == null ? Set.of() : Set.copyOf(authorities); + } } diff --git a/auth/src/main/java/com/baiyue/auth/service/AuthService.java b/auth/src/main/java/com/baiyue/auth/service/AuthService.java index 80ebbdfeb..aed118905 100644 --- a/auth/src/main/java/com/baiyue/auth/service/AuthService.java +++ b/auth/src/main/java/com/baiyue/auth/service/AuthService.java @@ -150,7 +150,8 @@ public class AuthService { return new TokenResponse("Bearer", accessToken, properties.accessTokenTtl().toSeconds(), rawRefresh, properties.refreshTokenTtl().toSeconds(), overseas == null ? null : overseas.accessToken(), - overseas == null ? 0L : overseas.expiresIn()); + overseas == null ? 0L : overseas.expiresIn(), + authorization.getRoles(), authorization.getPermissions()); } @Transactional 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 13a13cd35..5c90d612e 100644 --- a/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java +++ b/auth/src/main/java/com/baiyue/auth/service/OverseasTokenService.java @@ -57,8 +57,15 @@ public class OverseasTokenService { JwtClaimsSet claims = claimsBuilder.build(); String token = encoder.encode(JwtEncoderParameters.from( JwsHeader.with(SignatureAlgorithm.RS256).keyId(properties.currentKid()).build(), claims)).getTokenValue(); - return new OverseasTokenResponse("Bearer", token, properties.accessTokenTtl().toSeconds()); + return new OverseasTokenResponse("Bearer", token, properties.accessTokenTtl().toSeconds(), + authorization.getRoles(), authorization.getPermissions()); } - public record OverseasTokenResponse(String tokenType, String accessToken, long expiresIn) { } + public record OverseasTokenResponse(String tokenType, String accessToken, long expiresIn, + java.util.Set roles, java.util.Set authorities) { + public OverseasTokenResponse { + roles = roles == null ? java.util.Set.of() : java.util.Set.copyOf(roles); + authorities = authorities == null ? java.util.Set.of() : java.util.Set.copyOf(authorities); + } + } } diff --git a/auth/src/test/java/com/baiyue/auth/service/AuthServiceSmallJwtTest.java b/auth/src/test/java/com/baiyue/auth/service/AuthServiceSmallJwtTest.java index 31d936945..4b99948cc 100644 --- a/auth/src/test/java/com/baiyue/auth/service/AuthServiceSmallJwtTest.java +++ b/auth/src/test/java/com/baiyue/auth/service/AuthServiceSmallJwtTest.java @@ -72,7 +72,8 @@ class AuthServiceSmallJwtTest { when(jwtEncoder.encode(any())).thenReturn(encoded); when(encoded.getTokenValue()).thenReturn("small-token"); when(overseasTokenService.issue(account, snapshot)).thenReturn( - new OverseasTokenService.OverseasTokenResponse("Bearer", "overseas-token", 900)); + new OverseasTokenService.OverseasTokenResponse("Bearer", "overseas-token", 900, + snapshot.getRoles(), snapshot.getPermissions())); var response = service.login(new LoginRequest("operator", "secret")); @@ -98,6 +99,8 @@ class AuthServiceSmallJwtTest { verify(overseasTokenService).issue(account, snapshot); assertThat(response.overseasAccessToken()).isEqualTo("overseas-token"); assertThat(response.overseasExpiresIn()).isEqualTo(900); + assertThat(response.roles()).containsExactly("OVERSEAS_WAREHOUSE_PDA_OPERATOR"); + assertThat(response.authorities()).containsExactly("platform:order:list"); } @Test @@ -162,7 +165,8 @@ class AuthServiceSmallJwtTest { when(jwtEncoder.encode(any())).thenReturn(encoded); when(encoded.getTokenValue()).thenReturn("domestic-refreshed"); when(overseasTokenService.issue(account, snapshot)).thenReturn( - new OverseasTokenService.OverseasTokenResponse("Bearer", "overseas-refreshed", 900)); + new OverseasTokenService.OverseasTokenResponse("Bearer", "overseas-refreshed", 900, + snapshot.getRoles(), snapshot.getPermissions())); var response = service.refresh("refresh-old"); @@ -173,6 +177,8 @@ class AuthServiceSmallJwtTest { assertThat(response.refreshExpiresIn()).isEqualTo(604800); assertThat(response.overseasAccessToken()).isEqualTo("overseas-refreshed"); assertThat(response.overseasExpiresIn()).isEqualTo(900); + assertThat(response.roles()).containsExactly("MERCHANT_ADMIN"); + assertThat(response.authorities()).containsExactly("merchant:order:list"); verify(tokenSessionStore).consume("refresh-old"); verify(tokenSessionStore).store(anyString(), org.mockito.ArgumentMatchers.eq(52L), org.mockito.ArgumentMatchers.eq(Set.of("MERCHANT_ADMIN")), 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 0978b29d3..65c0769af 100644 --- a/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java +++ b/auth/src/test/java/com/baiyue/auth/service/OverseasTokenServiceTest.java @@ -82,6 +82,9 @@ class OverseasTokenServiceTest { .doesNotContainKeys("roles", "authorities", "permissions", "userId", "tenantId", "appCode", "permissionVersion"); assertThat(response.expiresIn()).isEqualTo(900); + assertThat(response.roles()).containsExactly("OVERSEAS_WAREHOUSE_PDA_OPERATOR"); + assertThat(response.authorities()).containsExactlyInAnyOrder(authority, merchantAuthority, + merchantCrossBorderAuthority, lastlegAuthority, financeAuthority, domesticAuthority); } @Test