首页 > 解决方案 > WebApp 托管一组 Oauth API 调用和控制访问

问题描述

我计划创建一个单一的战争文件(webapp),它将托管对不同后端系统的各种 API 调用。我将使用 OAuth2 通过 client_credentials 授权来控制访问。我计划向各种应用程序所有者发布 clientId/secrets,以控制应用程序对我的安全 API 的访问。

  1. 是否可以将我的 spring 安全配置配置为仅允许某些 clientId 访问特定 API 并阻止它们使用其他 API?例如,client123 可以从 apiA 调用 GET,但不能调用 PUT 到 apiB。
  2. 我考虑过使用范围,但似乎我的 CAS OAuth 服务器可能不支持 client_credentials 的范围。

标签: oauth-2.0spring-security-oauth2

解决方案


是的,Spring Security 支持多种模式,尽管您认为范围是首选方法是正确的。

我可能会建议您仍然在 Spring Security 方面使用范围,即使该表示仅存在于您的 API 中,这样随着 CAS 的成熟,或者如果您将来能够切换到范围,资源服务器将保持不变。

因此,假设您有一个使用 JWT 的 Spring Security OAuth 2.0 资源服务器:

@Override
protected void configure(HttpSecurity http) {
    http
        .oauth2ResourceServer()
            .jwt();
}

将 s 转换为Jwts的钩子是. 您的实现可能类似于:CollectionGrantedAuthorityConverter<Jwt, Collection<GrantedAuthority>>

public class ByClientIdJwtGrantedAuthoritiesConverter
    implements Converter<Jwt, Collection<GrantedAuthority>> {

    @Override
    public Collection<GrantedAuthority> convert(Jwt jwt) {
        // manually infer scopes from client ids
        String clientId = jwt.getSubject();
        if ("abc".equals(clientId)) {
            return Arrays.asList(new SimpleGrantedAuthority("SCOPE_read"));
        }
        // ... etc.
    }
}

然后你可以用以下方式连接它:

@Override
protected void configure(HttpSecurity http) {
    JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
    converter.setJwtGrantedAuthoritiesConverter(new ByClientIdJwtGrantedAuthoritiesConverter());
    http
        .oauth2ResourceServer()
            .jwt()
                .jwtAuthenticationConverter(converter);
}

我做了几个假设,包括如何从令牌中派生客户端,但总体思路就在那里。

几周后 Spring Security 5.2 GA 将支持不透明令牌,以防 OAuth2 CAS 不支持 JWT。在这种情况下,你会做类似的事情,只是用opaqueToken()DSL 代替。

此后,您可以像其他身份验证机制一样按路径配置 Spring Security:

@Override
protected void configure(HttpSecurity http) {
    http
        .authorizeRequests()
            .antMatchers("/apiA/**").hasAuthority("SCOPE_apiA")
            .antMatchers(HttpMethod.GET, "/apiB/**").hasAuthority("SCOPE_apiB:read")
            .and()
       .oauth2ResourceServer()
            .jwt()
                .jwtAuthenticationConverter(...);
}

推荐阅读