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

如何使用AWS Cognito的IAM角色实现Spring Boot接口的Spring Security权限控制?

问题根因

你遇到的403错误本质是两个核心问题:

  1. Spring Security OAuth2 默认不会自动解析cognito:roles字段为权限集合,需要手动映射到Spring的GrantedAuthority体系
  2. hasRole()方法会自动给权限值添加ROLE_前缀,你传入的完整ARN没有前缀,自然匹配失败
解决步骤

步骤1:自定义Cognito角色权限映射器

新增自定义权限映射逻辑,将cognito:roles中的角色转为Spring可识别的权限对象:

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

// 放在SecurityConfiguration类内部即可
private GrantedAuthoritiesMapper customAuthoritiesMapper() {
    return (authorities) -> {
        // 从OAuth2授权信息中提取用户属性
        Map<String, Object> attributes = authorities.stream()
            .filter(OAuth2UserAuthority.class::isInstance)
            .map(OAuth2UserAuthority.class::cast)
            .findFirst()
            .map(OAuth2UserAuthority::getAttributes)
            .orElse(Collections.emptyMap());
        
        // 提取cognito返回的角色列表
        Object rolesObj = attributes.get("cognito:roles");
        if (rolesObj instanceof Collection) {
            Collection<?> rawRoles = (Collection<?>) rolesObj;
            return rawRoles.stream()
                .map(Object::toString)
                // 如果要使用hasRole()方法,这里要加ROLE_前缀,示例:
                // .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                // 如果直接用hasAuthority()方法,不需要加前缀,直接用完整ARN
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
        }
        return Collections.emptyList();
    };
}

步骤2:将映射器注册到安全配置中

修改你的SecurityConfiguration的configure方法,把权限映射器配置到OAuth2登录流程:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf()
        .and()
        .authorizeRequests()
        .antMatchers("/login", "/", "/home", "/logout", "/ping").permitAll()
        // 注意这里改用hasAuthority,因为我们映射的时候没有加ROLE_前缀
        .antMatchers("/api/admin").hasAuthority("arn:aws:iam::xxxxxx:role/spring-sso-test-ADMIN")
        .antMatchers("/api/user").hasAuthority("arn:aws:iam::xxxxxx:role/spring-sso-test-USER")
        .anyRequest().authenticated()
        .and()
        .oauth2Login()
        // 注册自定义权限映射器
        .userInfoEndpoint()
        .userAuthoritiesMapper(customAuthoritiesMapper())
        .and()
        .and()
        .logout()
        .logoutSuccessUrl("/logout");
}

补充说明:hasRole("ADMIN")等价于hasAuthority("ROLE_ADMIN"),如果你的角色ARN不想加前缀,统一用hasAuthority是最简单的方案。

步骤3:开启注解权限校验支持(如果需要用@Secured/@PreAuthorize)

首先在你的安全配置类上添加@EnableGlobalMethodSecurity注解开启方法级权限校验:

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    // 原有配置不变
}

@Secured注解同样会默认匹配带ROLE_前缀的权限,如果你映射权限的时候没有加前缀,建议改用@PreAuthorize注解:

// 不需要ROLE_前缀的写法,和接口路径校验规则一致
@PreAuthorize("hasAuthority('arn:aws:iam::xxxxxx:role/spring-sso-test-ADMIN')")
@GetMapping(produces = "application/json")
public TestResponse get() {
    return new TestResponse("Admin API Response");
}
高版本Spring Boot适配说明

如果你使用的是Spring Boot 2.7+或3.x版本,WebSecurityConfigurerAdapter已经被废弃,建议改用SecurityFilterChain和GrantedAuthoritiesMapper Bean的写法即可,权限映射和校验逻辑和上述完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:54:06