如何在Java API中获取Angular应用的登录用户信息
问题诊断与解决方案
一、Basic认证无法获取用户信息的问题
当前代码存在两个核心问题导致无法获取认证用户信息:
- 未启用HTTP Basic认证:你的
WebSecurityConfig仅配置了CORS,但未开启Spring Security的HTTP Basic认证支持,导致请求中的Basic认证信息未被处理,请求始终处于匿名状态。 - 缺少用户认证数据源:没有配置可用于验证的用户信息(如内存用户或数据库用户),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配置无效的原因:
- Spring Security过滤器优先级高于CORS过滤器,导致OPTIONS预检请求被Security拦截。
- 仅调用
applyPermitDefaultValues()的配置可能不够宽松,无法适配Angular的跨域需求。
修复步骤
- 保留上述配置中的
csrf().disable()(Angular发送的是非表单请求,CSRF校验会拦截OPTIONS预检请求)。 - 细化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(); }
- 移除控制器上的
@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
相关产品推荐
相关产品推荐

