Spring Security-对OPTIONS调用的403状态响应 [英] Spring security - 403 status response on OPTIONS call
问题描述
我的后端托管在Heroku上,前端托管在Netlify上.当我在后端调用端点时,它将发送预检选项,但它的状态为403.我确实在寻找解决方案,但仍然无法正常工作.
I have backend hosted on Heroku, and frontend on Netlify. When I call endpoint on backend it sends preflight OPTIONS but it gives 403 status. I did search for solution but it still not working.
我希望能够使用主体为从FE到BE的"POST"
方法调用"/authenticate"
端点.
I want to be able to call "/authenticate"
endpoint with "POST"
method with body from FE to BE.
Spring安全性配置(仅是配置方法)
Spring security configuration (just configuration methods)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
...
@Override
public void configure(WebSecurity web) throws Exception
{
web.ignoring()
.antMatchers(HttpMethod.POST, "/authenticate", "/register")
.antMatchers(HttpMethod.GET, "/token")
.antMatchers("/h2-console/**")
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/authenticate").permitAll()
.antMatchers(HttpMethod.GET, "/user-data").authenticated()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of(<MY-URL>));
configuration.setAllowedHeaders(List.of("*"));
configuration.setMaxAge(Long.valueOf(3600));
configuration.setAllowedMethods(Arrays.asList("GET","POST", "OPTIONS"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
然后从FE拨打电话
var req = new XMLHttpRequest();
req.open('POST', API_URL + '/authenticate', true);
req.setRequestHeader("Content-Type", "application/json");
req.withCredentials = true;
req.onreadystatechange = function (aEvt) {
if (req.readyState === 4) {
if(req.status === 200) {
console.log(req.responseText);
isAuthenticationSucessful = true;
}
else
console.log("Error loading site");
}
};
req.send(JSON.stringify({username, password}));
浏览器开发工具:
Reason: CORS header 'Access-Control-Allow-Origin' missing
Reason: CORS request did not succeed
推荐答案
TL; DR
请确保在 setAllowedOrigins("https://myrul.com")
中没有斜杠,或者您的浏览器发送的原点完全相同.
Make sure that in setAllowedOrigins("https://myrul.com")
you don't have trailing slash or you have exactly the same origin that your browser send.
如果您的端点位于 web.ignoring(...
中,请从此处删除它,然后将其放入(与我的示例端点一起) http.authorizeRequests().antMatchers("/authenticate).permitAll()
If your endpoint is in web.ignoring(...
delete it from here and put it in (with my example endpoint) http.authorizeRequests().antMatchers("/authenticate").permitAll()
(根据我所讨论的代码,是 web
和 http
)
(web
and http
according to my code in question)
更长
所以我在评论中怎么说,使它无法正常工作的一件事是在 corsConfigurationSource
中设置 setAllowedOrigins("https://myrul.com/")
.请注意,后跟斜杠.
So how I said in my comment, one thing that make it not working correctly was setting setAllowedOrigins("https://myrul.com/")
in corsConfigurationSource
.
Notice that trailing slash.
但是我注意到在开发工具中,浏览器发送的原始标头是这样的: Origin:https://myrul.com
而不用斜杠结尾.为了使其正常工作,我必须将允许的原点更改为正确的原点,例如: setAllowedOrigins("https://myrul.com")
(不带斜杠).这使浏览器能够向服务器发送请求,并获得200个响应,但是浏览器不接受来自服务器cuz CORS的响应.
But I noticed in dev-tools that browser send origin header like this: Origin: https://myrul.com
without trailing slash. To make it works I have to change allowed origins to proper origin like this: setAllowedOrigins("https://myrul.com")
(without trailing slash).
This make browser able to send requests to server, and get 200 response, but browser don't accept response from server cuz CORS.
接下来的事情是,我将端点设置在 web.ignoring("/authenticate")...
中,并根据此问题春季安全配置-HttpSecurity与WebSecurity 该语句可防止Spring Security Filter Chain出现在标头 Access-Control-Allow-Origin
的位置,该标头告诉浏览器它可以接受响应. MDN Access-Control-Allow-Origin
The next thing was that I have my endpoint in web.ignoring("/authenticate")...
and according to this question
Spring Security Configuration - HttpSecurity vs WebSecurity
this statement prevents Spring Security Filter Chain where it should header Access-Control-Allow-Origin
which tell browser that it can accept response. MDN Access-Control-Allow-Origin
因此,答案是将我的端点从 web.ignoring("/authenticate")
转到 http.authorizeRequests().antMatchers("/authenticate").permitAll()
.
So the answer for that was take my endpoint from web.ignoring("/authenticate")
to http.authorizeRequests().antMatchers("/authenticate").permitAll()
.
但这会带来另一个问题,那就是现在要去过滤器链和我的自定义过滤器 http.addFilterBefore(new JwtFilter()...
),因此请确保采用自定义过滤器您的需要.
But this makes another problem, that is it will go now to filter chain and to my custom filter http.addFilterBefore(new JwtFilter()...
, so make sure to adopt custom filters to yours need.
这篇关于Spring Security-对OPTIONS调用的403状态响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!