【发布时间】:2023-03-10 11:30:01
【问题描述】:
我正在开发一个全栈应用程序,但遇到了一个问题。
我尝试从我的 Angular 应用程序向 Spring Boot 后端应用程序执行 POST 请求,但每次由于 CORS 而失败。事实上,如果我将 POST 更改为 GET 请求,它总是会成功。
这是我的前端代码:
finalizeRegister(userAccount: UserAccount) {
return this._httpClient.post(`${Constants.apiRoot}account/finalize`, userAccount);
}
和拦截器:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.url.startsWith(Constants.apiRoot)) {
return from(this._authService.getAccessToken().then(token => {
const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`);
const authReq = req.clone({ headers });
return next.handle(authReq).pipe(tap(_ => { }, error => {
var respError = error as HttpErrorResponse;
if (respError && (respError.status === 401 || respError.status === 403)) {
this._router.navigate(['/unauthorized']);
}
})).toPromise();
}));
}
else {
return next.handle(req);
}
}
春季启动CORS配置:
package pl.daniel.pawlowski.conquerorgame.security;
import com.auth0.spring.security.api.JwtWebSecurityConfigurer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
/**
* Configures our application with Spring Security to restrict access to our API endpoints.
*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value( "${auth0.audience}" )
private String audience;
@Value("${auth0.issuer}")
private String issuer;
@Override
protected void configure(HttpSecurity http) throws Exception {
JwtWebSecurityConfigurer
.forRS256(audience, issuer)
.configure(http)
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/public").permitAll()
.antMatchers(HttpMethod.GET, "/api/private").authenticated()
.antMatchers(HttpMethod.GET, "/api/admin/**").hasAuthority("view:admin")
.anyRequest()
.authenticated()
.and()
.cors();
}
@Bean
JwtDecoder jwtDecoder() {
/*
By default, Spring Security does not validate the "aud" claim of the token, to ensure that this token is
indeed intended for our app. Adding our own validator is easy to do:
*/
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder)
JwtDecoders.fromOidcIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
configuration.setAllowedHeaders(Arrays.asList("Authorization"));
return source;
}
}
我的配置似乎有问题,因为当我尝试使用 POST 请求调用任何端点时,在我的浏览器控制台中我看到:
访问 XMLHttpRequest 在 来自原点的“http://localhost:8081/api/account/finalize” “http://localhost:4200”已被 CORS 策略阻止:请求 标头字段内容类型不允许 预检响应中的 Access-Control-Allow-Headers。
【问题讨论】:
-
尝试使用 https 或在服务器端设置 cors 或尝试在客户端添加标头
-
该错误似乎表明 Spring 不喜欢您的 Angular 应用程序发送的
content-type标头。也许有一种方法可以配置 Cors 以允许某些(或所有)HTTP 标头?貌似有:docs.spring.io/spring-framework/docs/current/javadoc-api/org/… -
感谢@jrahhali,我已经设置:configuration.setAllowedHeaders(Arrays.asList("Authorization","content-type"));现在它可以工作了!