Webflux、Spring-Security、okta-spring-boot-starter、Okta-React如何正确使用CORS?
How to use CORS correctly for Webflux, Spring-Security, okta-spring-boot-starter, and Okta-React?
我的 webflux api 中有一个 CORS webFilter,当我通过邮递员为 pre-flight 清单发出选项请求时,我得到了正确的 headers 响应。但是,当我使用 Axios 和 Okta-React 库从浏览器发出相同的请求来检索访问令牌时,会返回 401 Unauthorized 并且不会返回我正在寻找的 headers 。 Axios 是否不在 OPTIONS 请求中包含 Bearer Token?我是否需要将不被 OKTA 验证的选项请求列入白名单,OKTA 不会处理这个吗?
我在邮递员中使用来自 SPA 的相同访问令牌。
我是否遗漏了 Axios 请求中的某些内容,是否需要使用 Axios for CORS 执行任何其他配置?
我很困惑,为什么 webfilter 在从邮递员发送时激活 OPTIONS 请求,但在浏览器中从 Axios 调用时却不激活?
const getExperience = () => {
const { accessToken } = authState;
axios({
method: "get",
timeout: 10000,
headers: {
"Authorization": `Bearer ${accessToken}`
},
url: `http://localhost:8080/api/v1/professionals`
}).then( response => {
setExperience(response.data);
});
}
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@EnableWebFluxSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class CustomCorsWebFilter implements WebFilter {
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN";
private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
private static final String ALLOWED_ORIGIN = "http://localhost:3000";
private static final String MAX_AGE = "3600";
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
if (exchange.getRequest().getMethod() == HttpMethod.OPTIONS) {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(exchange);
}
}
这是我用 WebFlux, React, and Okta.
设置 CORS headers 的方法
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
configuration.setAllowedMethods(Collections.singletonList("GET"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
我还使用了如下过滤器:
@Bean
CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(true);
corsConfig.setAllowedOrigins(List.of("*"));
corsConfig.setMaxAge(3600L);
corsConfig.addAllowedMethod("*");
corsConfig.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
我的 webflux api 中有一个 CORS webFilter,当我通过邮递员为 pre-flight 清单发出选项请求时,我得到了正确的 headers 响应。但是,当我使用 Axios 和 Okta-React 库从浏览器发出相同的请求来检索访问令牌时,会返回 401 Unauthorized 并且不会返回我正在寻找的 headers 。 Axios 是否不在 OPTIONS 请求中包含 Bearer Token?我是否需要将不被 OKTA 验证的选项请求列入白名单,OKTA 不会处理这个吗?
我在邮递员中使用来自 SPA 的相同访问令牌。 我是否遗漏了 Axios 请求中的某些内容,是否需要使用 Axios for CORS 执行任何其他配置?
我很困惑,为什么 webfilter 在从邮递员发送时激活 OPTIONS 请求,但在浏览器中从 Axios 调用时却不激活?
const getExperience = () => {
const { accessToken } = authState;
axios({
method: "get",
timeout: 10000,
headers: {
"Authorization": `Bearer ${accessToken}`
},
url: `http://localhost:8080/api/v1/professionals`
}).then( response => {
setExperience(response.data);
});
}
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@EnableWebFluxSecurity
public class SecurityConfiguration {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
}
}
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Component
public class CustomCorsWebFilter implements WebFilter {
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN";
private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
private static final String ALLOWED_ORIGIN = "http://localhost:3000";
private static final String MAX_AGE = "3600";
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
if (exchange.getRequest().getMethod() == HttpMethod.OPTIONS) {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(exchange);
}
}
这是我用 WebFlux, React, and Okta.
设置 CORS headers 的方法@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
configuration.setAllowedMethods(Collections.singletonList("GET"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
我还使用了如下过滤器:
@Bean
CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowCredentials(true);
corsConfig.setAllowedOrigins(List.of("*"));
corsConfig.setMaxAge(3600L);
corsConfig.addAllowedMethod("*");
corsConfig.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}