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

Spring MVC非Boot应用OAuth2/OIDC登录页不自动重定向问题

Spring Security OAuth2/OIDC 自动重定向问题排查与修复

问题描述

在非Spring Boot的Spring MVC应用中集成Spring Security OAuth2/OIDC,预期访问受保护端点(如/page)时,系统自动重定向到OIDC提供商的登录页(携带client_id等必要参数),但实际访问受保护端点时无任何反应。已配置Spring Security但未实现预期效果,希望通过Spring Security原生能力实现自动登录重定向,无需手动编写控制器逻辑。

用户当前配置代码:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorizeRequests ->
                authorizeRequests
                    .antMatchers("/page").authenticated()
                    .anyRequest().permitAll()
            )
            .oauth2Login()
            .and()
            .csrf().disable();
    }

    @Bean
    public ClientRegistrationRepository clientRegistrationRepository() {
        return new InMemoryClientRegistrationRepository(XClientRegistration());
    }

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository() {
        return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService());
    }

    @Bean
    public OAuth2AuthorizedClientService authorizedClientService() {
        return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository());
    }

    private ClientRegistration XClientRegistration() {
        logger.debug("Configuring x Client Registration");
        return ClientRegistrations
                .fromIssuerLocation("https://CONF.com/")
                .clientId("xxxx")
                .clientSecret("xxxx")
                .scope("openid")
                .redirectUri("/OAUTH2").build();
    }

}

问题分析

  1. 非Spring Boot环境自动配置缺失:Spring Boot会自动注册OAuth2相关过滤器、端点,但纯Spring MVC环境需要手动配置这些核心组件,否则Security规则无法生效。
  2. 回调URI配置不规范:自定义的/OAUTH2不符合Spring Security OAuth2的默认回调格式,导致认证流程无法闭环。
  3. 未明确登录触发端点:未指定OAuth2登录的入口端点,Spring Security无法引导未认证请求跳转至OIDC提供商。
  4. Web容器未加载Security过滤器:纯Spring MVC环境需手动配置DelegatingFilterProxy,否则Security的拦截逻辑不会生效。

修复方案

1. 修正ClientRegistration配置

调整回调URI为Spring Security OAuth2默认格式,同时指定客户端注册ID:

private static final String CLIENT_REGISTRATION_ID = "x-client";

private ClientRegistration XClientRegistration() {
    logger.debug("Configuring x Client Registration");
    return ClientRegistrations
            .fromIssuerLocation("https://CONF.com/")
            .clientId("xxxx")
            .clientSecret("xxxx")
            .scope("openid", "profile", "email") // 补充必要的OIDC权限范围
            .redirectUri("{baseUrl}/login/oauth2/code/" + CLIENT_REGISTRATION_ID)
            .registrationId(CLIENT_REGISTRATION_ID)
            .build();
}

2. 完善HttpSecurity配置

明确登录触发端点,并绑定客户端配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests(authorizeRequests ->
            authorizeRequests
                .antMatchers("/page").authenticated()
                .antMatchers("/login/oauth2/code/**", "/oauth2/authorization/**").permitAll() // 允许回调和登录端点访问
                .anyRequest().permitAll()
        )
        .oauth2Login(oauth2 -> oauth2
            .loginPage("/oauth2/authorization/" + CLIENT_REGISTRATION_ID) // 指定OAuth2登录入口
            .clientRegistrationRepository(clientRegistrationRepository())
            .authorizedClientRepository(authorizedClientRepository())
        )
        .csrf().disable();
}

3. 配置Web容器加载Security过滤器

在web.xml中添加DelegatingFilterProxy,确保Spring Security的拦截链生效:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4. 确保依赖完整(纯Spring MVC环境)

手动引入OAuth2相关依赖(Maven示例):

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
    <version>5.7.11</version> <!-- 版本需与Spring核心版本匹配 -->
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-jose</artifactId>
    <version>5.7.11</version>
</dependency>

完整修改后代码

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
    private static final String CLIENT_REGISTRATION_ID = "x-client";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests(authorizeRequests ->
                authorizeRequests
                    .antMatchers("/page").authenticated()
                    .antMatchers("/login/oauth2/code/**", "/oauth2/authorization/**").permitAll()
                    .anyRequest().permitAll()
            )
            .oauth2Login(oauth2 -> oauth2
                .loginPage("/oauth2/authorization/" + CLIENT_REGISTRATION_ID)
                .clientRegistrationRepository(clientRegistrationRepository())
                .authorizedClientRepository(authorizedClientRepository())
            )
            .csrf().disable();
    }

    @Bean
    public ClientRegistrationRepository clientRegistrationRepository() {
        return new InMemoryClientRegistrationRepository(XClientRegistration());
    }

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository() {
        return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService());
    }

    @Bean
    public OAuth2AuthorizedClientService authorizedClientService() {
        return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository());
    }

    private ClientRegistration XClientRegistration() {
        logger.debug("Configuring x Client Registration");
        return ClientRegistrations
                .fromIssuerLocation("https://CONF.com/")
                .clientId("xxxx")
                .clientSecret("xxxx")
                .scope("openid", "profile", "email")
                .redirectUri("{baseUrl}/login/oauth2/code/" + CLIENT_REGISTRATION_ID)
                .registrationId(CLIENT_REGISTRATION_ID)
                .build();
    }

}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:03:15