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

Spring Boot集成Keycloak如何配置支持认证/匿名访问的可选鉴权端点

问题原因

你现在卡壳的核心是两个配置语义没搞对:

  • 配keycloak.securityConstraints[0].authRoles[0] = *的时候,规则是这个路径必须是已认证用户才能进,不管什么角色都行,匿名请求直接被Keycloak过滤器拦在外面,根本到不了控制器
  • 把安全约束全删了之后,Keycloak默认不会给非受保护的路径解析请求头里带的Token,就算请求带了合法的Bearer Token,控制器里拿的Principal也会是null

实现方案

根据你用的整合方式二选一调整就行:

场景1:直接用Keycloak官方Spring Boot Starter,没写自定义Spring Security配置

  1. 把application.properties里原来的安全约束配置替换成下面的:
# 配置公共路径,不强制要求认证
keycloak.securityConstraints[0].securityCollections[0].name = public
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /*
# 注意:这个约束不要配authRoles属性,就代表路径允许匿名访问

# 核心开关
keycloak.bearer-only = true # 用Bearer Token模式校验凭证,没带Token或者Token无效的时候不跳登录页,直接放行
keycloak.ssl-required = external
keycloak.principal-attribute = preferred_username
keycloak.use-resource-role-mappings = true
  1. 改下控制器代码,避免空指针和类型转换报错:
@RestController
public class HelloController {

    @GetMapping("/")
    public String index(Principal principal) {
        // 先判断Principal类型,匿名访问的时候Principal要么是null要么是匿名身份对象,直接返回公共内容
        if (principal instanceof KeycloakPrincipal) {
            KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) principal;
            String username = keycloakPrincipal.getKeycloakSecurityContext().getToken().getPreferredUsername();
            return "Hello " + username;
        }
        return "Hello";
    }
}

如果你用Java 16及以上版本,直接用instanceof KeycloakPrincipal keycloakPrincipal的模式匹配写法省掉强转步骤就行。

场景2:自己写Spring Security配置类整合Keycloak

如果是通过继承KeycloakWebSecurityConfigurerAdapter做安全配置,直接调整HttpSecurity的访问规则就可以:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
                .csrf().disable()
                .authorizeRequests()
                // 目标路径设为permitAll,允许匿名访问,Keycloak过滤器会自动解析请求带的有效Token填充认证上下文
                .antMatchers("/").permitAll()
                // 其他需要强制登录的路径正常配置规则就行
                .anyRequest().authenticated()
                .and()
                // 开匿名身份配置,没带有效凭证的请求会被赋予匿名身份,正常进到控制器
                .anonymous();
    }

    // 剩下的Keycloak相关配置(会话策略、密钥配置之类的)保持原来的逻辑不用改
}

控制器代码和场景1的写法完全一致。


注意事项
  • 别给需要支持匿名访问的路径配authRoles=*,这个配置等价于Spring Security里的authenticated(),会把所有没认证的请求直接拦下来
  • 别上来就把Principal直接强转成KeycloakPrincipal,必须先做类型判断,不然匿名访问的时候必抛空指针或者类型转换异常
  • 要是按上面配置完还是拿不到已认证用户信息,先检查是不是自己加的自定义过滤器提前清空了SecurityContext,或者把Keycloak的认证过滤器设成了只拦截受保护路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:42:16