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

添加Spring Security后,无法获取Apache AJP传递的RemoteUser问题

解决Spring Security引入后无法获取Apache通过AJP传递的RemoteUser问题

我之前处理过一模一样的场景——当你在Spring Boot项目中加入Spring Security依赖后,它会全盘接管应用的认证逻辑,默认不会自动识别Apache通过AJP协议传递过来的远程用户信息,这就是你调用request.getRemoteUser()返回null的核心原因。

下面是一步步的解决方案:

1. 确保Spring Boot的AJP配置正确

首先要保证你的Spring Boot应用已经开启AJP支持,并且信任Apache所在的代理服务器。在application.properties(或application.yml)中添加以下配置:

server.ajp.enabled=true
# 替换成你的Apache服务器实际IP,允许该IP传递认证信息
server.ajp.trusted-proxies=127.0.0.1
server.ajp.protocol=AJP/1.3

2. 配置Spring Security接收预认证用户信息

Spring Security需要明确配置,让它信任Apache已经完成的认证,并提取Apache通过AJP传递的REMOTE_USER信息。创建一个Spring Security配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityCustomizer;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            // 添加预认证过滤器,优先处理Apache传递的用户信息
            .addFilterBefore(requestHeaderAuthenticationFilter(), RequestHeaderAuthenticationFilter.class)
            .authenticationProvider(preAuthenticatedAuthenticationProvider());
        
        // 如果你的场景不需要CSRF保护(比如内部系统SSO),可以关闭
        http.csrf(csrf -> csrf.disable());
        
        return http.build();
    }

    @Bean
    public RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter() {
        RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
        // 指定从哪个请求头/属性获取用户名,Apache通过AJP传递的默认是REMOTE_USER
        filter.setPrincipalRequestHeader("REMOTE_USER");
        // 因为Apache已经完成认证,不需要凭证信息
        filter.setCredentialsRequestHeader(null);
        filter.setAuthenticationManager(authentication -> authentication);
        return filter;
    }

    @Bean
    public PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() {
        PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
        // 配置用户详情服务,这里简单返回一个默认用户,你可以根据实际需求扩展(比如从数据库加载权限)
        provider.setPreAuthenticatedUserDetailsService(userDetailsService());
        return provider;
    }

    @Bean
    public AuthenticationUserDetailsService userDetailsService() {
        return token -> new org.springframework.security.core.userdetails.User(
            token.getPrincipal().toString(),
            "",
            java.util.Collections.singletonList(new org.springframework.security.core.authority.SimpleGrantedAuthority("ROLE_USER"))
        );
    }

    // 可选:放行静态资源(如果有需要)
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().requestMatchers("/static/**");
    }
}

3. 验证Apache的AJP配置

最后确认你的Apache配置中,已经正确将认证后的用户名通过AJP传递给Spring Boot。比如:

# AJP代理配置
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/

# 确保SSO认证后的用户名被放入REMOTE_USER头传递给后端
RequestHeader set REMOTE_USER %{REMOTE_USER}s

完成以上配置后,重新启动Spring Boot应用,再次访问/sso接口,request.getRemoteUser()就能正确获取到Apache传递的用户名了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:29:12