我已经配置了spring安全性,但仍然无法通过angular发送帖子请求:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.authenticationProvider(credentialsAuthenticationProvider)
.httpBasic()
.and()
.logout()
.and()
.cors().configurationSource(corsConfigurationSource)
.and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
/* To allow Pre-flight [OPTIONS] request from browser */
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
我的cors配置源如下:
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
List<String> allowedOrigins = new LinkedList<>();
allowedOrigins.add("*");
List<String> allowedHeaders = new LinkedList<>();
allowedHeaders.add("*");
List<String> allowedMethods = new LinkedList<>();
allowedMethods.add("HEAD");
allowedMethods.add("GET");
allowedMethods.add("POST");
allowedMethods.add("PUT");
allowedMethods.add("DELETE");
allowedMethods.add("PATCH");
allowedMethods.add("OPTIONS");
configuration.setAllowedOrigins(allowedOrigins);
configuration.setAllowedMethods(allowedMethods);
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(allowedHeaders);
allowedHeaders.add("Authorization");
allowedHeaders.add("Content-Type");
allowedHeaders.add("x-xsrf-token");
allowedHeaders.add("xsrf-token");
allowedHeaders.add("Accept-language");
allowedHeaders.add("X-Requested-With");
configuration.setAllowedHeaders(allowedHeaders);
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
并且我正在使用根上下文:api / v1,可能会有所帮助。
在Angular端,我已配置app.module.ts
imports: [
...
HttpClientModule,
HttpClientXsrfModule,
],
当我尝试发布请求时出现问题:这是请求和响应的屏幕截图:
GET请求返回200 OK:
发布请求返回禁止的403:
奇怪的是,有2个XSRF令牌,我想这是问题的根源。
答案 0 :(得分:0)
要解决弹簧安全性和角度之间的csrf问题,您必须这样做。
将-lt
替换为
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
默认的角度csrf拦截器并不总是有效。因此,您必须实现自己的拦截器。
csrf()
.ignoringAntMatchers ("/login","/logout")
.csrfTokenRepository (this.getCsrfTokenRepository());
}
private CsrfTokenRepository getCsrfTokenRepository() {
CookieCsrfTokenRepository tokenRepository =
CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepository.setCookiePath("/");
return tokenRepository;
}
最后将其添加到您的提供程序(app.module.ts)
import {Injectable, Inject} from '@angular/core';
import {HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler,
HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";
@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let requestMethod: string = req.method;
requestMethod = requestMethod.toLowerCase();
if (requestMethod && (requestMethod === 'post' || requestMethod === 'delete' || requestMethod === 'put')) {
const headerName = 'X-XSRF-TOKEN';
let token = this.tokenExtractor.getToken() as string;
if (token !== null && !req.headers.has(headerName)) {
req = req.clone({headers: req.headers.set(headerName, token)});
}
}
return next.handle(req);
}
}
考虑放入您的进口商品。
providers: [{ provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }]