优化
This commit is contained in:
-49
@@ -1,49 +0,0 @@
|
||||
package com.baiyue.common.security;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class GatewayAccessTokenSessionValidatorTest {
|
||||
private final GatewayAccessTokenSessionValidator validator =
|
||||
new GatewayAccessTokenSessionValidator("gateway-secret");
|
||||
|
||||
@Test void acceptsOnlyGatewayAuthenticatedAuthorizationSnapshot() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.TOKEN_HEADER, "gateway-secret");
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.ROLES_HEADER, "PLATFORM_ADMIN");
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.AUTHORITIES_HEADER,
|
||||
"platform:overseas-warehouse:last-mile-order:list,platform:finance:fee-source:view");
|
||||
|
||||
AccessTokenSession session = validator.validate(jwt(), request);
|
||||
|
||||
assertThat(session.userId()).isEqualTo(42L);
|
||||
assertThat(session.roles()).containsExactly("PLATFORM_ADMIN");
|
||||
assertThat(session.permissions()).containsExactlyInAnyOrder(
|
||||
"platform:overseas-warehouse:last-mile-order:list", "platform:finance:fee-source:view");
|
||||
}
|
||||
|
||||
@Test void rejectsForgedOrMissingGatewayToken() {
|
||||
MockHttpServletRequest forged = new MockHttpServletRequest();
|
||||
forged.addHeader(GatewayAccessTokenSessionValidator.TOKEN_HEADER, "forged");
|
||||
forged.addHeader(GatewayAccessTokenSessionValidator.AUTHORITIES_HEADER,
|
||||
"platform:overseas-warehouse:last-mile-order:list");
|
||||
assertThatThrownBy(() -> validator.validate(jwt(), forged))
|
||||
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("Invalid overseas gateway");
|
||||
|
||||
assertThatThrownBy(() -> validator.validate(jwt(), new MockHttpServletRequest()))
|
||||
.isInstanceOf(IllegalArgumentException.class).hasMessageContaining("Missing overseas gateway");
|
||||
}
|
||||
|
||||
private Jwt jwt() {
|
||||
return Jwt.withTokenValue("small-overseas-token").header("alg", "RS256").subject("42")
|
||||
.issuedAt(Instant.now()).expiresAt(Instant.now().plusSeconds(300))
|
||||
.claim("tenant_id", 0L).claim("app_code", "PLATFORM")
|
||||
.claim("permission_version", 7L).claim("token_version", 1).build();
|
||||
}
|
||||
}
|
||||
+15
-8
@@ -29,7 +29,8 @@ class JwtAuthenticationFilterTest {
|
||||
.claim("user_id", 1L).build();
|
||||
JwtDecoder decoder = token -> jwt;
|
||||
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(decoder, new JwtClaimsMapper(),
|
||||
new JsonAuthenticationEntryPoint(new ObjectMapper()));
|
||||
new JsonAuthenticationEntryPoint(new ObjectMapper()),
|
||||
token -> new AccessTokenSession(1, 1L, java.util.Set.of(), java.util.Set.of()));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer valid");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@@ -43,20 +44,25 @@ class JwtAuthenticationFilterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticatesMinimalOverseasTokenWithGatewaySnapshot() throws Exception {
|
||||
void authenticatesUnifiedTokenWithServerSessionIgnoringGatewayHeaders() throws Exception {
|
||||
Jwt jwt = Jwt.withTokenValue("overseas").header("alg", "RS256").subject("42")
|
||||
.issuedAt(Instant.now()).expiresAt(Instant.now().plusSeconds(60))
|
||||
.claim("tenant_id", 0L).claim("app_code", "PLATFORM")
|
||||
.claim("jti", "session-42").claim("user_id", 42L).claim("tenant_id", 0L).claim("app_code", "PLATFORM")
|
||||
.claim("permission_version", 7L).claim("token_version", 1).build();
|
||||
var redis = org.mockito.Mockito.mock(org.springframework.data.redis.core.StringRedisTemplate.class);
|
||||
var values = org.mockito.Mockito.mock(org.springframework.data.redis.core.ValueOperations.class);
|
||||
org.mockito.Mockito.when(redis.opsForValue()).thenReturn(values);
|
||||
org.mockito.Mockito.when(values.get("baiyue:auth:access:session-42"))
|
||||
.thenReturn("{\"version\":1,\"userId\":42,\"roles\":[\"PLATFORM_ADMIN\"],\"permissions\":[\"platform:lastleg:view\"]}");
|
||||
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(token -> jwt, new JwtClaimsMapper(),
|
||||
new JsonAuthenticationEntryPoint(new ObjectMapper()),
|
||||
new GatewayAccessTokenSessionValidator("gateway-secret"));
|
||||
new RedisAccessTokenSessionValidator(redis, "baiyue:auth"));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/api/platform/v1/last-leg/orders");
|
||||
request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer overseas");
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.TOKEN_HEADER, "gateway-secret");
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.ROLES_HEADER, "PLATFORM_ADMIN");
|
||||
request.addHeader(GatewayAccessTokenSessionValidator.AUTHORITIES_HEADER, "platform:lastleg:view");
|
||||
request.addHeader("X-Internal-Service-Token", "gateway-secret");
|
||||
request.addHeader("X-Overseas-Roles", "FORGED_ADMIN");
|
||||
request.addHeader("X-Overseas-Authorities", "platform:wallet:write");
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
AtomicBoolean invoked = new AtomicBoolean();
|
||||
|
||||
@@ -64,7 +70,8 @@ class JwtAuthenticationFilterTest {
|
||||
var authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
assertThat(authentication).isNotNull();
|
||||
assertThat(authentication.getAuthorities()).extracting("authority")
|
||||
.contains("APP_PLATFORM", "ROLE_PLATFORM_ADMIN", "platform:lastleg:view");
|
||||
.contains("APP_PLATFORM", "ROLE_PLATFORM_ADMIN", "platform:lastleg:view")
|
||||
.doesNotContain("ROLE_FORGED_ADMIN", "platform:wallet:write");
|
||||
invoked.set(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baiyue.common.security;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.support.StaticListableBeanFactory;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class UnifiedSessionModeTest {
|
||||
@Test
|
||||
void rejectsLegacySessionModesAndMissingRedisInsteadOfTrustingClaimsOrHeaders() {
|
||||
var configuration = new BaiyueSecurityAutoConfiguration();
|
||||
var beans = new StaticListableBeanFactory();
|
||||
var redis = beans.getBeanProvider(StringRedisTemplate.class);
|
||||
for (String mode : new String[]{"claims", "gateway", "unknown", "redis"}) {
|
||||
assertThatThrownBy(() -> configuration.jwtAuthenticationFilter(token -> null,
|
||||
new JwtClaimsMapper(), new JsonAuthenticationEntryPoint(new ObjectMapper()),
|
||||
redis, new ObjectMapper(), "baiyue:auth", mode))
|
||||
.isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user