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

配置Keycloak Spring Boot Adapter:/api用Bearer Only,/login重定向登录

解决Keycloak Spring Boot Adapter接口认证模式区分问题

核心思路

先关闭全局的bearer-only模式,再通过Spring Security细粒度配置不同路径的认证规则:

  • /api/**路径强制使用Bearer Token认证(即Bearer Only,未认证返回401)
  • 其他路径支持重定向到Keycloak OIDC登录页面

步骤1:修改Keycloak全局配置

在application.yml(或application.properties)中,将全局bearer-only设为false——这是实现重定向登录的前提,全局设为true会强制所有接口仅接受Bearer Token,无法触发重定向流程。

示例application.yml配置:

keycloak:
  auth-server-url: http://你的Keycloak地址/auth
  realm: 你的Realm名称
  resource: 你的客户端ID
  credentials:
    secret: 你的客户端密钥(仅当客户端为confidential类型时需要)
  bearer-only: false
  use-resource-role-mappings: true

步骤2:配置Spring Security规则

根据你使用的Spring Security版本,选择对应的配置方式:

方式一:使用最新的SecurityFilterChain(推荐)

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.web.SecurityFilterChain;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 配置路径权限规则
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login").permitAll()  // 允许匿名访问/login路径
                .requestMatchers("/api/**").authenticated()  // /api/**路径必须认证
                .anyRequest().authenticated()  // 其他路径也需认证(可按需调整)
            )
            // 配置OIDC登录流程,自动重定向到Keycloak登录页
            .oauth2Login()
            // 配置资源服务器,对/api/**使用Bearer Token认证
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    .jwtAuthenticationConverter(keycloakJwtConverter())
                )
            )
            // 处理认证异常:/api路径返回401,其他路径重定向登录
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(new KeycloakAuthenticationEntryPoint())
            );

        return http.build();
    }

    // 自定义JWT转换,提取Keycloak中的角色(按需添加)
    private JwtAuthenticationConverter keycloakJwtConverter() {
        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(new KeycloakRoleConverter());
        return converter;
    }
}

方式二:使用旧版KeycloakWebSecurityConfigurerAdapter(兼容老项目)

import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
        authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(authProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new NullAuthenticatedSessionStrategy();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
            .authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/api/**").authenticated()
                .anyRequest().authenticated()
            .and()
            .exceptionHandling()
                .authenticationEntryPoint(new KeycloakAuthenticationEntryPoint());
    }
}

关键说明

  1. /login路径的作用:无需手动实现登录页面,当未认证用户访问需要登录的非/api路径时,Keycloak Adapter会自动重定向到Keycloak官方登录页,登录成功后跳转回原请求路径。
  2. Bearer Only模式的实现:/api/**路径配置为authenticated(),结合资源服务器逻辑,会强制要求请求携带有效的Bearer Token,未携带/无效时直接返回401 Unauthorized,不会触发重定向。
  3. 客户端配置:确保Keycloak客户端的访问类型为public或confidential,若为confidential需在配置中填写客户端密钥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:21:24