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

Keycloak与Spring Boot:实现按用户限制访问权限

实现Spring Boot + Keycloak按用户ID限制资源访问的方案

当然可以实现这种用户级的资源访问控制!你之前看到的角色权限是粗粒度的管控,而按用户ID匹配路径属于细粒度的资源隔离,不管是用KeycloakWebSecurityConfigurerAdapter还是新版本的Spring Security配置方式,都能轻松搞定。下面给你两种实用的实现方案:

方案一:方法级安全注解(简单直接)

这种方式适合在Controller层面精准控制单个接口,步骤非常简单:

  1. 先开启方法级安全支持,在你的Security配置类上加上@EnableGlobalMethodSecurity(prePostEnabled = true);
  2. 在对应的Controller方法上,用@PreAuthorize注解编写SpEL表达式,匹配路径里的userId和当前认证用户的ID。

示例代码:

@RestController
@RequestMapping("/api")
public class UserProfileController {

    // 仅允许路径中的userId与当前登录用户ID一致时访问
    @GetMapping("/{userId}/edit")
    @PreAuthorize("#userId == authentication.name")
    public ResponseEntity<String> editUserProfile(@PathVariable String userId) {
        // 你的业务逻辑代码
        return ResponseEntity.ok("允许编辑用户 " + userId + " 的信息");
    }
}

注意:如果你的userId对应Keycloak用户的唯一标识sub(而非用户名),需要调整表达式:

@PreAuthorize("#userId == authentication.attributes['sub']")

Keycloak会把用户的sub、用户名、邮箱等信息存入Authentication的attributes集合,你可以根据业务需求选择对应的属性。

方案二:全局URL规则配置(统一管控)

如果你想在Security配置里统一设置这类路径的访问规则,不用给每个Controller方法加注解,可以用HttpSecurity的access()方法结合SpEL表达式实现:

基于KeycloakWebSecurityConfigurerAdapter的配置(旧版本兼容)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider authProvider = keycloakAuthenticationProvider();
        // 转换Keycloak角色格式为Spring Security兼容的Authority
        authProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(authProvider);
    }

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

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        // 读取Spring Boot配置文件中的Keycloak配置
        return new KeycloakSpringBootConfigResolver();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                // 针对/api/{userId}/edit路径设置权限规则
                .antMatchers("/api/{userId}/edit")
                .access("#request.pathVariables['userId'] == authentication.name")
                // 其他接口的权限规则按需配置
                .anyRequest().authenticated();
    }
}

新版本Spring Security(无WebSecurityConfigurerAdapter)

如果你的Spring Boot版本是2.7+(对应Spring Security 5.7+),WebSecurityConfigurerAdapter已被标记为废弃,推荐使用SecurityFilterChain的方式配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private final KeycloakAuthenticationProvider keycloakAuthProvider;

    public SecurityConfig(KeycloakAuthenticationProvider keycloakAuthProvider) {
        this.keycloakAuthProvider = keycloakAuthProvider;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(auth -> auth
                        .antMatchers("/api/{userId}/edit")
                        .access("#request.pathVariables['userId'] == authentication.attributes['sub']")
                        .anyRequest().authenticated()
                )
                .authenticationProvider(keycloakAuthProvider)
                .oauth2ResourceServer(oauth2 -> oauth2.jwt());

        return http.build();
    }

    @Bean
    public KeycloakConfigResolver keycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}

额外注意事项

  • 确保你的Keycloak客户端配置中开启了openid scope,这样用户的sub、用户名等信息才会被正确传递到Spring Security的Authentication对象中;
  • 若需要自定义用户信息获取逻辑,可以实现UserDetailsService或自定义KeycloakAuthenticationProvider来扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 07:17:28