我使用的是一个Angular 前端和一个带有Spring Security 的spring后端。
http
.cors().and()
// .csrf().disable()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.authorizeRequests()
// .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/xrtool/*").permitAll()
.antMatchers("/advanced_search").hasRole("USER")
.antMatchers("/creation").hasRole("USER")
.antMatchers("/edit").hasRole("USER")
.antMatchers("/basicAuth").permitAll()
.antMatchers("/**").permitAll()
.anyRequest().authenticated().and()
.httpBasic();
我在访问没有保护(permitAll)的API时没有问题,但是那些需要特定角色的API给予了我一个未经授权的状态401。我相信这是由于我的客户端在初始身份验证请求后没有自动设置cookie。
我的授权请求代码:
authenticate(username : string, password : string){
let authHeader = new HttpHeaders({
authorization : 'Basic ' + btoa(username + ':' + password),
withCredentials: 'true'
});
return this.http.get(`${API_URL}/basicAuth`, {headers: authHeader})
}
我的后台代码:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
@Override
protected void configure(HttpSecurity http) {
try {
http
.cors().and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.authorizeRequests()
.antMatchers("/xrtool/*").permitAll()
.antMatchers("/advanced_search").hasRole("USER")
.antMatchers("/creation").hasRole("USER")
.antMatchers("/edit").hasRole("USER")
.antMatchers("/basicAuth").permitAll()
.antMatchers("/**").permitAll()
.anyRequest().authenticated().and()
.httpBasic();
} catch (Exception e){
System.out.println(e);
}
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
我的初始请求的响应头:
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Allow-Credentials: true
Set-Cookie: XSRF-TOKEN=475b11b6-39a4-4a46-a58d-e096a3bc07c6; Path=/
Set-Cookie: JSESSIONID=3E8382E29CB7C0AD9BBC168EA08ACF30; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 21 Jan 2023 17:56:43 GMT
Keep-Alive: timeout=60
Connection: keep-alive
以及后续的请求头:
GET /xrtool/Test HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/109.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
withCredentials: true
Origin: http://localhost:4200
DNT: 1
Connection: keep-alive
Referer: http://localhost:4200/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
网络客户端的存储也不包含Cookie。
我已经用不同的浏览器(Chrome,Firefox,Edge)试过了,但结果是一致的。
我试着直接访问API(localhost:8080/api/request),一切正常。我还可以看到webclient存储中的cookie。
Postman也工作得很好。我可以看到cookie被保存在标头中,在初始授权请求之后,后续请求被授权。
我尝试通过拦截器在每个请求中添加授权头,并且我能够访问API。
编辑:
感谢Tr 1 Monsters的观察,我能够找到这个问题。withCredentials头在错误的位置。似乎它不需要在初始身份验证请求中,但每个后续请求。我已经将它添加到我的Http-Intercept中,如下所示:
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let username = "b"
let password = "b"
let basicAuthHeaderString = "Basic " + window.btoa(username + ':' + password)
request = request.clone({
setHeaders: {
// Authorization: basicAuthHeaderString
}
, withCredentials: true
})
return next.handle(request);
}
我保留了原来的方式,添加了头,以显示withCredentials头被放置在setHeaders部分之外。
1条答案
按热度按时间iibxawm41#
感谢Tr 1 Monsters的观察,我能够找到这个问题。withCredentials头在错误的位置。似乎它不需要在初始身份验证请求中,但每个后续请求。我已经像这样将它添加到我的Http-Interceptor:
我保留了添加头的原始方式,以显示withCredentials头放置在setHeaders部分之外。