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

基于Keycloak 22与Spring Boot 3.1,如何用OAuth2AuthorizationRequestRedirectFilter拦截请求?

使用OAuth2AuthorizationRequestRedirectFilter拦截Keycloak跳转请求(Spring Boot 3.1 + Keycloak 22)

要在请求跳转到Keycloak之前拦截授权URL,你可以通过自定义OAuth2AuthorizationRequestRedirectFilter子类实现,这个过滤器是Spring Security OAuth2中负责将用户重定向到授权服务器(Keycloak)的核心组件。以下是完整实现示例:

1. 自定义拦截过滤器

继承OAuth2AuthorizationRequestRedirectFilter,重写sendRedirect方法——这是触发跳转前的最后拦截点,你可以在这里添加自定义逻辑:

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;

public class CustomKeycloakRedirectFilter extends OAuth2AuthorizationRequestRedirectFilter {

    public CustomKeycloakRedirectFilter(OAuth2AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository) {
        super(authorizationRequestRepository);
    }

    @Override
    protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String redirectUri) throws IOException {
        // 拦截逻辑示例1:打印即将跳转的Keycloak授权URL
        System.out.println("即将跳转至Keycloak授权端点: " + redirectUri);
        
        // 拦截逻辑示例2:修改授权URL参数(比如添加自定义参数)
        // String modifiedUri = redirectUri + (redirectUri.contains("?") ? "&" : "?") + "custom_param=my_value";
        
        // 拦截逻辑示例3:自定义校验,不满足则阻止跳转
        // if (!validateRequest(request)) {
        //     response.sendError(HttpServletResponse.SC_FORBIDDEN, "无权访问Keycloak授权");
        //     return;
        // }

        // 执行默认跳转逻辑(如果修改了URL,就传入modifiedUri)
        super.sendRedirect(request, response, redirectUri);
    }

    // 可选:自定义请求校验方法
    private boolean validateRequest(HttpServletRequest request) {
        // 这里可以添加你的校验逻辑,比如检查请求来源、用户状态等
        return true;
    }
}

2. 配置Spring Security替换默认过滤器

在Spring Security配置类中,将自定义过滤器注册到OAuth2登录流程的授权端点,替换默认的过滤器:

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.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth
                        .anyRequest().authenticated()
                )
                .oauth2Login(oauth2 -> oauth2
                        .authorizationEndpoint(authEndpoint -> authEndpoint
                                // 指定授权请求的存储仓库
                                .authorizationRequestRepository(authorizationRequestRepository())
                                // 替换为自定义的跳转过滤器
                                .authorizationRequestRedirectFilter(customKeycloakRedirectFilter())
                        )
                )
                .exceptionHandling(ex -> ex
                        .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/oauth2/authorization/keycloak"))
                );

        return http.build();
    }

    @Bean
    public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
        // 使用HttpSession存储授权请求
        return new HttpSessionOAuth2AuthorizationRequestRepository();
    }

    @Bean
    public CustomKeycloakRedirectFilter customKeycloakRedirectFilter() {
        return new CustomKeycloakRedirectFilter(authorizationRequestRepository());
    }
}

关键说明

  • sendRedirect方法是拦截跳转的核心时机:在调用父类的sendRedirect前,你可以完全控制是否跳转、修改跳转URL、添加业务校验等。
  • 版本适配:Spring Boot 3.1搭配的Spring Security 6.1使用Jakarta Servlet API(取代了旧的javax),所以代码中导入的是jakarta.servlet.http.*包。
  • 如果需要更深度定制授权请求(比如修改scope、clientId等),可以重写buildAuthorizationRequest方法,直接操作OAuth2AuthorizationRequest对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 02:05:30