You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular跨域请求未携带授权Cookie(已配置withCredentials)

问题解决:Angular跨域请求未携带Cookie导致401

核心原因

浏览器的同源策略限制了跨域请求自动携带Cookie,只有当请求被判定为同域(或通过代理伪装成同域)时,才会自动附带Cookie。你的Postman测试正常是因为Postman不受浏览器同源策略约束,而代理模式下前端与代理服务器同域,因此能正常传递Cookie。

解决方案

1. 后端Spring Boot配置CORS允许凭证

必须明确指定允许的源(不能用*),同时开启allowCredentials:

全局CORS配置(WebMvc)

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("http://localhost:4200") // 必须指定具体源,不能用*
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true) // 关键:允许携带凭证
                .maxAge(3600);
    }
}

若使用Spring Security,需额外配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and() // 启用CORS配置
            .csrf().disable() // 本地开发可临时禁用,生产环境按需配置
            .authorizeRequests()
            .antMatchers("/api/login").permitAll()
            .anyRequest().authenticated();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/api/**", config);
        return source;
    }
}

2. 前端Angular请求开启凭证携带

确保每个跨域请求都设置withCredentials: true,可通过单个请求配置或全局拦截器实现:

单个请求配置

import { HttpClient } from '@angular/common/http';

// 示例请求
this.http.get('http://localhost:8080/api/test', { withCredentials: true })
  .subscribe(res => {
    // 处理响应
  });

全局拦截器(推荐,无需每个请求单独设置)

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class CredentialsInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // 克隆请求并开启凭证携带
    const modifiedRequest = req.clone({ withCredentials: true });
    return next.handle(modifiedRequest);
  }
}

然后在app.module.ts中注册拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { CredentialsInterceptor } from './credentials.interceptor';

@NgModule({
  providers: [
    { 
      provide: HTTP_INTERCEPTORS, 
      useClass: CredentialsInterceptor, 
      multi: true 
    }
  ]
})
export class AppModule { }

验证步骤

  1. 重启Spring Boot后端和Angular前端
  2. 调用/api/login接口后,打开浏览器开发者工具→Application→Cookies,确认已存储后端设置的Cookie
  3. 调用/api/test接口时,查看Network→请求头,确认Cookie字段已被携带
  4. 检查响应头,确保存在Access-Control-Allow-Credentials: true,且Access-Control-Allow-Origin为http://localhost:4200(而非*)

注意事项

  • 禁止同时设置allowedOrigins: "*"和allowCredentials: true,浏览器会直接拒绝这种不合规配置
  • 若后端设置的Cookie为HttpOnly,前端JS无法读取该Cookie,但不影响请求自动携带
  • 确保Cookie的Domain和Path配置正确,本地开发时Domain应为localhost,Path可设为/或/api

内容的提问来源于stack exchange,提问作者Craig Armstrong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:05:21