2 changed files with 78 additions and 1 deletions
@ -0,0 +1,76 @@ |
|||
package com.mydreamjob.config; |
|||
|
|||
import org.junit.jupiter.api.Test; |
|||
import org.junit.jupiter.params.ParameterizedTest; |
|||
import org.junit.jupiter.params.provider.ValueSource; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; |
|||
import org.springframework.boot.test.context.SpringBootTest; |
|||
import org.springframework.boot.test.mock.mockito.MockBean; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.test.context.ActiveProfiles; |
|||
import org.springframework.test.web.servlet.MockMvc; |
|||
|
|||
import static org.hamcrest.Matchers.containsString; |
|||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
|||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; |
|||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; |
|||
|
|||
@SpringBootTest(properties = { |
|||
"spring.datasource.url=jdbc:h2:mem:cors_context_path;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE", |
|||
"spring.jpa.show-sql=false", |
|||
"app.cors.allowed-origins=http://localhost:5173,http://localhost:3000" |
|||
}) |
|||
@AutoConfigureMockMvc |
|||
@ActiveProfiles("integration-test") |
|||
class CorsContextPathIntegrationTest { |
|||
@Autowired MockMvc mvc; |
|||
@MockBean RedisTemplate<String, Object> redis; |
|||
|
|||
@ParameterizedTest |
|||
@ValueSource(strings = {"http://localhost:5173", "http://localhost:3000"}) |
|||
void configuredOriginCanPreflightIdentitySelectionWithApplicationContext(String origin) throws Exception { |
|||
mvc.perform(options("/api/v1/auth/identity/select") |
|||
.contextPath("/api/v1").servletPath("/auth/identity/select") |
|||
.header("Origin", origin) |
|||
.header("Access-Control-Request-Method", "POST") |
|||
.header("Access-Control-Request-Headers", "authorization,content-type")) |
|||
.andExpect(status().isOk()) |
|||
.andExpect(header().string("Access-Control-Allow-Origin", origin)) |
|||
.andExpect(header().string("Access-Control-Allow-Credentials", "true")) |
|||
.andExpect(header().string("Access-Control-Allow-Methods", containsString("POST"))) |
|||
.andExpect(header().string("Access-Control-Allow-Headers", containsString("authorization"))); |
|||
} |
|||
|
|||
@ParameterizedTest |
|||
@ValueSource(strings = {"http://localhost:5173", "http://localhost:3000"}) |
|||
void configuredOriginCanRead401WithoutBypassingAuthentication(String origin) throws Exception { |
|||
mvc.perform(get("/api/v1/auth/me") |
|||
.contextPath("/api/v1").servletPath("/auth/me") |
|||
.header("Origin", origin)) |
|||
.andExpect(status().isUnauthorized()) |
|||
.andExpect(header().string("Access-Control-Allow-Origin", origin)); |
|||
} |
|||
|
|||
@Test |
|||
void unconfiguredOriginRemainsRejected() throws Exception { |
|||
mvc.perform(options("/api/v1/auth/identity/select") |
|||
.contextPath("/api/v1").servletPath("/auth/identity/select") |
|||
.header("Origin", "https://untrusted.example") |
|||
.header("Access-Control-Request-Method", "POST")) |
|||
.andExpect(status().isForbidden()) |
|||
.andExpect(header().doesNotExist("Access-Control-Allow-Origin")); |
|||
} |
|||
|
|||
@Test |
|||
void unconfiguredHeaderRemainsRejected() throws Exception { |
|||
mvc.perform(options("/api/v1/auth/identity/select") |
|||
.contextPath("/api/v1").servletPath("/auth/identity/select") |
|||
.header("Origin", "http://localhost:5173") |
|||
.header("Access-Control-Request-Method", "POST") |
|||
.header("Access-Control-Request-Headers", "x-unapproved-header")) |
|||
.andExpect(status().isForbidden()) |
|||
.andExpect(header().doesNotExist("Access-Control-Allow-Origin")); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue