spring Angular客户端未使用JSessionID设置Cookie

nukf8bse  于 2023-04-10  发布在  Spring
关注(0)|答案(1)|浏览(94)

我使用的是一个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部分之外。

iibxawm4

iibxawm41#

感谢Tr 1 Monsters的观察,我能够找到这个问题。withCredentials头在错误的位置。似乎它不需要在初始身份验证请求中,但每个后续请求。我已经像这样将它添加到我的Http-Interceptor:

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部分之外。

相关问题