如何使用基于范围的@PreAuthorize 来保护spring-security-oauth 资源?

How to protect spring-security-oauth resources using @PreAuthorize based on Scope?

我成功配置了 spring-security-oauth2,这样外部应用程序就可以通过我的应用程序进行身份验证。但是,根据外部应用程序和用户允许的内容,客户只能访问我的 API 的一个子集。可用子集由 OAuth 范围决定。

在经典的 Spring 应用程序中,我可以使用 @PreAuthorize 来强制执行基于角色的边界:

@Controller
public class MyController {
  @PreAuthorize("hasRole('admin')")
  @RequestMapping("...")
  public String doStuff() {
    // ...
  }
}

在使用 OAuth 和范围而不是角色时,我该如何做同样的事情?

Spring OAuth 附带了 OAuth2MethodSecurityExpressionHandler,class 添加了使用 @PreAuthorize 表达式进行此类检查的能力。您需要做的就是注册此 class,例如如果您使用的是 Javaconfig,则像这样:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

现在您可以简单地使用:

@PreAuthorize("#oauth2.hasScope('requiredScope')")

保护您的请求方法。要查看除 hasScope 之外还有哪些方法可用,请检查 class OAuth2SecurityExpressionMethods.

缺点是 OAuth2MethodSecurityExpressionHandler 扩展了 DefaultMethodSecurityExpressionHandler,因此您不能将它与其他同样扩展此 class 的 classes 结合使用。

作为替代方案,您也可以 map OAuth scopes to classic user roles