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

如何在Java API中获取Angular应用的登录用户信息

问题诊断与解决方案

一、Basic认证无法获取用户信息的问题

当前代码存在两个核心问题导致无法获取认证用户信息:

  1. 未启用HTTP Basic认证:你的WebSecurityConfig仅配置了CORS,但未开启Spring Security的HTTP Basic认证支持,导致请求中的Basic认证信息未被处理,请求始终处于匿名状态。
  2. 缺少用户认证数据源:没有配置可用于验证的用户信息(如内存用户或数据库用户),Spring Security无法校验请求中的账号密码。

修复步骤

修改WebSecurityConfig,添加HTTP Basic认证配置,并配置测试用内存用户:

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;

import javax.servlet.http.HttpServletRequest;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    // 配置密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 配置内存测试用户
    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withUsername("testuser")
                .password(passwordEncoder().encode("testpass"))
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().disable() // 非表单请求关闭CSRF,避免拦截预检请求
                .cors().configurationSource(new CorsConfigurationSource() {
                    @Override
                    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                        return new CorsConfiguration().applyPermitDefaultValues();
                    }
                })
                .and()
                .httpBasic(); // 启用Basic认证
    }
}

修改后,用Insomnia发送Basic认证请求(账号testuser、密码testpass),接口就能获取到正确的用户信息,比如SecurityContextHolder.getContext().getAuthentication().getName()会返回testuser而非anonymousUser。

二、CORS配置无效的问题

当前CORS配置无效的原因:

  1. Spring Security过滤器优先级高于CORS过滤器,导致OPTIONS预检请求被Security拦截。
  2. 仅调用applyPermitDefaultValues()的配置可能不够宽松,无法适配Angular的跨域需求。

修复步骤

  1. 保留上述配置中的csrf().disable()(Angular发送的是非表单请求,CSRF校验会拦截OPTIONS预检请求)。
  2. 细化CORS配置,适配Angular应用:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .csrf().disable()
            .cors().configurationSource(request -> {
                CorsConfiguration config = new CorsConfiguration();
                // 替换为你的Angular应用实际域名
                config.addAllowedOrigin("http://localhost:4200");
                config.addAllowedMethod("*");
                config.addAllowedHeader("*");
                config.setAllowCredentials(true); // 允许携带认证信息
                return config;
            })
            .and()
            .httpBasic();
}
  1. 移除控制器上的@CrossOrigin注解,避免全局配置和局部注解冲突。

三、接口获取用户信息的优化建议

可以简化接口代码,用更简洁的方式获取用户信息:

@GetMapping("/getUserName")
public String getUserName() {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && !auth.getName().equals("anonymousUser")) {
        return auth.getName();
    }
    return "未认证";
}

或使用@AuthenticationPrincipal(需确保认证已生效):

@GetMapping("/getUserNameAuthenticationPrincipal")
public String getUserNameAuthenticationPrincipal(@AuthenticationPrincipal UserDetails userDetails) {
    return userDetails != null ? userDetails.getUsername() : "未认证";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 00:49:53