优化
This commit is contained in:
+45
@@ -0,0 +1,45 @@
|
||||
package com.baiyue.common.security;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class HttpSessionStateVerifierTest {
|
||||
@Test void acceptsOnlyExplicitSuccessAndNeverForwardsBearer() throws Exception {
|
||||
var body = new AtomicReference<>("{\"code\":\"200\",\"data\":true}");
|
||||
var auth = new AtomicReference<String>();
|
||||
var internal = new AtomicReference<String>();
|
||||
var input = new AtomicReference<String>();
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|
||||
server.createContext("/validate", exchange -> {
|
||||
auth.set(exchange.getRequestHeaders().getFirst("Authorization"));
|
||||
internal.set(exchange.getRequestHeaders().getFirst("X-Internal-Service-Token"));
|
||||
input.set(new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8));
|
||||
byte[] bytes = body.get().getBytes(StandardCharsets.UTF_8);
|
||||
exchange.sendResponseHeaders(200, bytes.length); exchange.getResponseBody().write(bytes); exchange.close();
|
||||
});
|
||||
server.start();
|
||||
try {
|
||||
var verifier = new HttpSessionStateVerifier("http://127.0.0.1:" + server.getAddress().getPort() + "/validate", "internal-only", new ObjectMapper());
|
||||
verifier.verify("session", 42L);
|
||||
assertThat(auth.get()).isNull(); assertThat(internal.get()).isEqualTo("internal-only");
|
||||
assertThat(new ObjectMapper().readTree(input.get()).path("userId").longValue()).isEqualTo(42);
|
||||
for (String rejected : new String[]{"{}", "{\"code\":200,\"data\":true}", "{\"code\":\"200\",\"data\":false}",
|
||||
"{\"code\":\"A0403\",\"data\":true}", "{\"code\":\"200\",\"data\":\"true\"}", "not-json"}) {
|
||||
body.set(rejected);
|
||||
assertThatThrownBy(() -> verifier.verify("session", 42L)).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
} finally { server.stop(0); }
|
||||
}
|
||||
|
||||
@Test void unavailableAuthorityFailsClosed() throws Exception {
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|
||||
int port = server.getAddress().getPort(); server.start(); server.stop(0);
|
||||
var verifier = new HttpSessionStateVerifier("http://127.0.0.1:" + port + "/validate", "internal", new ObjectMapper());
|
||||
assertThatThrownBy(() -> verifier.verify("session", 42L)).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ class JwtAuthenticationFilterTest {
|
||||
.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 RedisAccessTokenSessionValidator(redis, "baiyue:auth"));
|
||||
new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), org.mockito.Mockito.mock(SessionStateVerifier.class)));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setRequestURI("/api/platform/v1/last-leg/orders");
|
||||
request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer overseas");
|
||||
|
||||
+5
-5
@@ -24,7 +24,7 @@ class RedisAccessTokenSessionValidatorTest {
|
||||
when(values.get("baiyue:auth:access:jti-1"))
|
||||
.thenReturn("{\"version\":1,\"userId\":1,\"roles\":[\"ADMIN\"],\"permissions\":[\"order:read\"]}");
|
||||
|
||||
assertThatCode(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth")
|
||||
assertThatCode(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), mock(SessionStateVerifier.class))
|
||||
.validate(jwt("jti-1"))).doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class RedisAccessTokenSessionValidatorTest {
|
||||
when(redis.opsForValue()).thenReturn(values);
|
||||
when(values.get("baiyue:auth:access:jti-1")).thenReturn(null);
|
||||
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth")
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), mock(SessionStateVerifier.class))
|
||||
.validate(jwt("jti-1")))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("revoked or expired");
|
||||
@@ -49,7 +49,7 @@ class RedisAccessTokenSessionValidatorTest {
|
||||
when(values.get("baiyue:auth:access:jti-1"))
|
||||
.thenThrow(new RedisConnectionFailureException("offline"));
|
||||
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth")
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), mock(SessionStateVerifier.class))
|
||||
.validate(jwt("jti-1")))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("unavailable");
|
||||
@@ -63,7 +63,7 @@ class RedisAccessTokenSessionValidatorTest {
|
||||
when(values.get("baiyue:auth:access:jti-1"))
|
||||
.thenReturn("{\"version\":1,\"userId\":2,\"roles\":[],\"permissions\":[]}");
|
||||
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth")
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), mock(SessionStateVerifier.class))
|
||||
.validate(jwt("jti-1")))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("identity mismatch");
|
||||
@@ -76,7 +76,7 @@ class RedisAccessTokenSessionValidatorTest {
|
||||
when(redis.opsForValue()).thenReturn(values);
|
||||
when(values.get("baiyue:auth:access:jti-1")).thenReturn("not-json");
|
||||
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth")
|
||||
assertThatThrownBy(() -> new RedisAccessTokenSessionValidator(redis, "baiyue:auth", new com.fasterxml.jackson.databind.ObjectMapper(), mock(SessionStateVerifier.class))
|
||||
.validate(jwt("jti-1")))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("Invalid access token session");
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ class UnifiedSessionModeTest {
|
||||
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))
|
||||
redis, new ObjectMapper(), "baiyue:auth", mode, "http://auth:9100/internal/auth/accounts/sessions/validate", "test-token"))
|
||||
.isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user