暂存提交
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package com.baiyue.gateway.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
class AppScopeAuthorizationManagerTest {
|
||||
@Test
|
||||
void acceptsMatchingApplicationScope() {
|
||||
var manager = new AppScopeAuthorizationManager("MERCHANT");
|
||||
StepVerifier.create(manager.check(Mono.just(authentication("MERCHANT")), null))
|
||||
.expectNextMatches(decision -> decision.isGranted())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsDifferentApplicationScope() {
|
||||
var manager = new AppScopeAuthorizationManager("PLATFORM");
|
||||
StepVerifier.create(manager.check(Mono.just(authentication("MERCHANT")), null))
|
||||
.expectNextMatches(decision -> !decision.isGranted())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMissingApplicationScope() {
|
||||
var manager = new AppScopeAuthorizationManager("PLATFORM");
|
||||
Jwt jwt = Jwt.withTokenValue("token")
|
||||
.header("alg", "none")
|
||||
.subject("1")
|
||||
.issuedAt(Instant.now())
|
||||
.expiresAt(Instant.now().plusSeconds(60))
|
||||
.build();
|
||||
StepVerifier.create(manager.check(Mono.just(new JwtAuthenticationToken(
|
||||
jwt, java.util.List.of(new SimpleGrantedAuthority("authenticated")))), null))
|
||||
.expectNextMatches(decision -> !decision.isGranted())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private JwtAuthenticationToken authentication(String appCode) {
|
||||
Jwt jwt = Jwt.withTokenValue("token")
|
||||
.header("alg", "none")
|
||||
.subject("1")
|
||||
.issuedAt(Instant.now())
|
||||
.expiresAt(Instant.now().plusSeconds(60))
|
||||
.claim("app_code", appCode)
|
||||
.build();
|
||||
return new JwtAuthenticationToken(jwt,
|
||||
java.util.List.of(new SimpleGrantedAuthority("authenticated")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.baiyue.gateway.config;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {
|
||||
"spring.cloud.nacos.discovery.enabled=false",
|
||||
"spring.cloud.nacos.discovery.register-enabled=false",
|
||||
"spring.cloud.nacos.config.enabled=false",
|
||||
"spring.cloud.gateway.discovery.locator.enabled=false",
|
||||
"baiyue.security.jwt-secret=test-jwt-secret-at-least-32-bytes-long",
|
||||
"baiyue.cors.allowed-origins=http://localhost:5173"
|
||||
})
|
||||
@AutoConfigureWebTestClient
|
||||
class GatewayCorsConfigurationTest {
|
||||
private static final String PROFILE_URL =
|
||||
"http://localhost/api/merchant/v1/iam/tenant/profile";
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
void allowedOriginCanCompletePutPreflightWithoutToken() {
|
||||
webTestClient.options()
|
||||
.uri(PROFILE_URL)
|
||||
.header(HttpHeaders.ORIGIN, "http://localhost:5173")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.PUT.name())
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "authorization,content-type")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "http://localhost:5173")
|
||||
.expectHeader().value(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,
|
||||
value -> org.assertj.core.api.Assertions.assertThat(value).contains("PUT"))
|
||||
.expectHeader().value(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
|
||||
value -> org.assertj.core.api.Assertions.assertThat(value.toLowerCase())
|
||||
.contains("authorization", "content-type"))
|
||||
.expectHeader().doesNotExist(HttpHeaders.WWW_AUTHENTICATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectedOriginDoesNotReceiveCorsPermission() {
|
||||
webTestClient.options()
|
||||
.uri(PROFILE_URL)
|
||||
.header(HttpHeaders.ORIGIN, "https://untrusted.example.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.PUT.name())
|
||||
.exchange()
|
||||
.expectStatus().isForbidden()
|
||||
.expectHeader().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void corsDoesNotMakeProtectedActualRequestAnonymous() {
|
||||
webTestClient.get()
|
||||
.uri(PROFILE_URL)
|
||||
.header(HttpHeaders.ORIGIN, "http://localhost:5173")
|
||||
.exchange()
|
||||
.expectStatus().isUnauthorized()
|
||||
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "http://localhost:5173");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user