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

Angular调用Spring Security接口出现ERR_TOO_MANY_REDIRECTS 302错误

问题分析:Spring Security + Angular登录出现ERR_TOO_MANY_REDIRECTS错误

你使用Spring Security v6.1.0实现认证功能,Postman向/login发送POST请求能正常获取响应,但Angular发起请求时出现GET http://localhost:8081/login net::ERR_TOO_MANY_REDIRECTS 302错误,问题根源在于前后端认证方式不匹配,导致重定向循环,具体原因及解决方案如下:


核心问题点

1. 表单登录与Basic Auth的冲突

你的Spring Security配置采用的是**表单登录(formLogin)**流程,但Angular端却在请求头中添加了Authorization: Basic ...字段,触发了Spring Security的Basic认证过滤器。两种认证流程互相干扰:

  • 表单登录依赖Session Cookie维护认证状态,而Basic Auth是基于请求头的单次认证
  • Spring Security先尝试Basic认证,认证成功后触发重定向到/loginUser,但如果会话未正确建立,/loginUser的请求会被判定为未认证,再次重定向到/login,形成循环

2. 请求格式不匹配

Spring Security的表单登录默认接收application/x-www-form-urlencoded格式的POST请求,参数为username和password,但Angular端发送的是JSON格式请求,同时额外携带Basic Auth头,不符合表单登录的预期格式,导致认证失败,触发重定向到登录页,反复重定向超出浏览器限制。


解决方案

方案一:改用Basic Authentication(适配Angular当前实现)

修改Spring Security配置,启用Basic认证,移除表单登录相关配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors().and().csrf().disable()
                .authorizeHttpRequests((authorize) -> authorize
                        .requestMatchers("/", "/login").permitAll()
                        .anyRequest().authenticated()
                )
                .httpBasic(Customizer.withDefaults()) // 启用Basic认证
                .cors((cors) -> cors
                        .configurationSource(corsConfigurationSource())
                );

        return http.build();
    }

    // 保留Cors、passwordEncoder等其他Bean配置
}

同时调整Angular的AuthService,直接请求认证后的接口验证状态,无需发送JSON体:

authenticate(username: string, password: string) {
    const httpOptions = {
        headers: new HttpHeaders({
            'Authorization': "Basic " + btoa(username + ":" + password)
        })
    };

    // 直接请求需要认证的/loginUser接口验证身份
    return this.http.get('http://localhost:8081/loginUser', httpOptions).pipe(
        map((user) => {
            let authString = 'Basic ' + btoa(username + ':' + password);
            sessionStorage.setItem('username', username);
            sessionStorage.setItem('basicAuth', authString);
            this.isLoggedIn = true;
            return user;
        }),
        catchError((error) => {
            console.error('Authentication error:', error);
            return throwError(error);
        })
    );
}

方案二:保持表单登录,修正Angular请求格式

让Angular发送符合表单登录要求的请求格式,移除Basic Auth头,同时开启Cookie携带:

authenticate(username: string, password: string) {
    // 构建x-www-form-urlencoded格式的参数
    const params = new URLSearchParams();
    params.set('username', username);
    params.set('password', password);

    const httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/x-www-form-urlencoded'
        }),
        withCredentials: true // 携带Session Cookie
    };

    return this.http.post(AUTH_API, params.toString(), httpOptions).pipe(
        map(() => {
            // 表单登录成功后,Session由Cookie维护,无需存储Basic Auth信息
            sessionStorage.setItem('username', username);
            this.isLoggedIn = true;
        }),
        catchError((error) => {
            console.error('Authentication error:', error);
            return throwError(error);
        })
    );
}

同时删除Angular组件中不安全的密码存储代码:

// 移除这行代码
sessionStorage.setItem('password', this.form.password);

额外建议

如果是前后端分离架构,更推荐使用JWT认证方式,避免Session和Cookie带来的跨域问题,同时简化状态维护逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 06:32:10