Spring Security系列(31)- Spring Security Oauth2之scope作用域机制使用详解

OAuth 2.0协议 关于Scope的说明

概念

Scope是 OAuth 2.0 中的一种机制,用于限制应用程序对用户帐户的访问。应用程序可以请求一个或多个范围,然后该信息会在同意屏幕中呈现给用户,并且颁发给应用程序的访问令牌将仅限于授予的范围。

OAuth 规范允许授权服务器或用户根据请求修改授予应用程序的范围,尽管在实践中这样做的服务示例并不多。

OAuth 没有为范围定义任何特定值,因为它高度依赖于服务的内部架构和需求。

GitHub 文档描述

通过作用域,您可以准确指定所需的访问权限类型。 作用域限制 OAuth 令牌的访问权限。 它们不会授予超出用户权限范围的任何额外权限。

在 GitHub 上设置 OAuth 应用程序时,请求的作用域会在授权表单上显示给用户。

例如通过授权码获取访问令牌后,可以通过以下方式查询当前作用域:

$ curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com/users/codertocat -I
HTTP/2 200
X-OAuth-Scopes: repo, user \\ 列出令牌已授权的作用域。
X-Accepted-OAuth-Scopes: user \\ 列出操作检查的作用域。

GitHub定义了一些可用作用域
在这里插入图片描述

流程

使用案例

授权码模式入门参考文档

1. 添加作用域

在数据库或者内存中,给当前客户端添加了三个作用域。
在这里插入图片描述

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    
        // 配置客户端
        clients
                // 使用内存设置
                .inMemory()
                // client_id
                .withClient("client")
                // client_secret
                .secret(passwordEncoder.encode("secret"))
                // 授权类型: 授权码、刷新令牌、密码、客户端、简化模式、短信验证码 "refresh_token"
                .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "sms_code")
                // 授权范围,也可根据这个范围标识,进行鉴权
                .scopes("admin:org","write:org","read:org")
                .accessTokenValiditySeconds(300)
                .refreshTokenValiditySeconds(3000)
                // 授权码模式 授权页面是否自动授权
                //.autoApprove(false)
                // 拥有的权限
                .authorities("add:user")
                // 允许访问的资源服务 ID
                //.resourceIds("oauth2-resource-server001-demo")
                // 注册回调地址
                .redirectUris("http://localhost:20000/code");
    }

2. 授权页面选择scope

授权使用不带scope参数访问授权码端点:

http://localhost:20000/oauth/authorize?client_id=client&client_secret=secret&response_type=code

可以看到授权页面会弹出所有的scope范围
在这里插入图片描述
如果携带了scope参数,则表明只需要对当前作用域进行授权:

http://localhost:20000/oauth/authorize?client_id=client&client_secret=secret&response_type=code&scope=admin:org

在这里插入图片描述
如果当前客户端没有配置scope作用域,申请的时候也没有传递scope参数,则会报错:

Handling OAuth2 error: error="invalid_scope", error_description="Empty scope (either the client or the user is not allowed the requested scopes)"

3.资源服务器对于scope的访问控制

授权获取到授权码以后,申请访问令牌,通过访问令牌访问资源服务器。先看下这时认证信息都有些啥
在这里插入图片描述
可以看到当前令牌对应的认证信息,包含授权码模式中的用户及Oauth信息,OAuth2Request对象,就保存了授权时的scope信息,如果没有授权的scope则不会出现在这里。

这样资源服务器也就获取到了scope数据,那么具体应该怎么使用scope进行访问控制呢?

之前有分析过Security 基于注解的权限控制@PreAuthorize等注解的使用方法,在spring-security-oauth也提供了相应的表达式,我们只需要在注解中使用oauth2相关的表达式就可以了。

在源码中,可以看到Oauth2相关的表达式写法,其中就有对scope作用域的访问控制。
在这里插入图片描述

以下例子,可以使用hasScope,表示当前Oauth应用,毕竟具有admin:user的作用域,否则会拒绝访问.

    @GetMapping("/resource")
    @PreAuthorize("#oauth2.hasScope('admin:user')") //
    public String resource(){
    
    
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        System.out.println(authentication.toString());
        return "访问到了resource 资源 ";
    }

可以看到当前没有admin:user,所以去访问资源的服务器时会报错。
在这里插入图片描述

在这里插入图片描述

总结

通过以上案例分析,Spring Security Oauth2除了使用resourceId对服务级别进行控制,也能基于scope 添加更小粒度的控制。

Guess you like

Origin blog.csdn.net/qq_43437874/article/details/121552989