[译]在 Spring 中实现 OAuth2:使用范围(第 2 部分)

我们在上一篇文章中了解了基本的 OAuth2 概念以及如何在 Spring 中实现和执行不同的授权。在这篇文章中,我们将介绍 OAuth2 的另一个重要概念:范围。

OAuth 范围

保护对应用程序的访问通常分两个步骤进行:身份验证和授权。要理解这两个概念,假设您在绝密政府大楼工作。在开始之前,你会得到一张卡片,可以让你进入建筑物。 OAuth 令牌可以看作是允许您访问的卡片。

一旦你进去,你决定去三楼见你的一位同事,在尝试使用你的卡打开三楼的门后,你听到一声嘟嘟声,告诉你你没有被授权。在 OAuth 中,范围是一种定义令牌可以访问哪些资源以及不能访问哪些资源的方法。范围允许访问控制,并且可以被视为相当于传统身份验证中的用户角色。

实现

为了演示范围,我们将使用第 1 部分中的示例

资源服务器的控制器中,我们有以下端点:

typescript 复制代码
@RestController("/")
public class ResourceController {

    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

    @GetMapping("/foo")
    public String foo(){
        return "foo";
    }

    @PostMapping("/bar")
    public String bar(){
        return "bar";
    }

    @DeleteMapping("/test")
    public String test(){
        return "test";
    }
}

第一步是使用所需的范围配置授权服务器

arduino 复制代码
 clients.inMemory().withClient("my-trusted-client")
                .authorizedGrantTypes("password",
                        "refresh_token", "implicit", "client_credentials", "authorization_code")
                .authorities("CLIENT")
                .scopes("read", "write", "trust")
                .accessTokenValiditySeconds(60)
                .redirectUris("http://localhost:8081/test.html")
                .resourceIds("resource")
                .secret("mysecret");

要在资源服务器中启用范围检查,我们有两个选项:使用安全配置或使用方法安全性。

  • 使用安全配置:
scss 复制代码
	@Override
	public void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
			 .antMatchers(HttpMethod.GET,"/hello").access("#oauth2.hasScope('read')")
			 .antMatchers(HttpMethod.GET,"/foo").access("#oauth2.hasScope('read')")
			 .antMatchers(HttpMethod.POST,"/bar").access("#oauth2.hasScope('write')")
			 .antMatchers(HttpMethod.DELETE,"/test").access("#oauth2.hasScope('trust')")
			.anyRequest().authenticated().
			 and().csrf().disable();
	}
  • 使用方法安全性:
kotlin 复制代码
    @PreAuthorize("#oauth2.hasScope('read')")
    @GetMapping("/hello")
    public String hello(){
        return "hello";
    }

    @PreAuthorize("#oauth2.hasScope('read')")
    @GetMapping("/foo")
    public String foo(){
        return "foo";
    }

    @PreAuthorize("#oauth2.hasScope('write')")
    @PostMapping("/bar")
    public String bar(){
        return "bar";
    }

    @PreAuthorize("#oauth2.hasScope('trust')")
    @DeleteMapping("/test")
    public String test(){
        return "test";
    }

另外,我们需要将 @EnableGlobalMethodSecurity(prePostEnabled = true) 添加到 Spring 可以获取的任何类( @Configuration@Service 等)。在我们的示例中,我们已将其添加到 ResourceSecurityConfiguration 类中。 prePostEnabled = true 告诉 Spring 启用前注解和后注解,例如 @PreAuthorize@PostFilter 等......

对于那些想了解 #oauth2.hasScope('trust') 这样的表达式的人来说,它们是使用 Spring 表达式语言(SpEL)构建的。

行动范围

默认情况下,如果令牌请求中不存在范围,Spring 会假定令牌具有所有配置的范围。让我们首先请求一个具有 read 范围的令牌:

bash 复制代码
curl -X POST --user my-trusted-client:mysecret localhost:8081/oauth/token -d 'grant_type=client_credentials&client_id=my-trusted-client&scope=read' -H "Accept: application/json"

回复:

json 复制代码
{
  "access_token": "acadbb31-f126-411d-ae5b-6a278cee2ed6",
  "token_type": "bearer",
  "expires_in": 60,
  "scope": "read"
}

现在,我们可以使用令牌来访问具有 read 范围访问权限的端点:

bash 复制代码
 curl -XGET localhost:8989/hello -H "Authorization: Bearer acadbb31-f126-411d-ae5b-6a278cee2ed6"

 hello

curl -XGET localhost:8989/foo -H "Authorization: Bearer acadbb31-f126-411d-ae5b-6a278cee2ed6"

 foo

现在,让我们尝试在仅接受 write 范围的端点上使用此令牌:

bash 复制代码
curl -XPOST localhost:8989/bar -H "Authorization: Bearer acadbb31-f126-411d-ae5b-6a278cee2ed6"

回复:

json 复制代码
{
  "error": "access_denied",
  "error_description": "Access is denied"
}

由于令牌不具有所需的范围,因此访问被拒绝。让我们尝试获取一个具有 write 范围的新令牌,然后重试:

bash 复制代码
curl -X POST --user my-trusted-client:mysecret localhost:8081/oauth/token -d 'grant_type=client_credentials&client_id=my-trusted-client&scope=write' -H "Accept: application/json"

回复:

json 复制代码
{
  "access_token": "bf0fa83a-23bd-4633-ac6c-a06f40d53e5f",
  "token_type": "bearer",
  "expires_in": 3599,
  "scope": "write"
}
bash 复制代码
curl -XPOST localhost:8989/bar -H "Authorization: Bearer bf0fa83a-23bd-4633-ac6c-a06f40d53e5f"

bar

总结

范围是 OAuth 的一个重要方面,因为令牌不携带有关其用户或请求者的信息。范围允许限制对资源的访问,以实现更好的访问控制和安全性。在下一篇文章中,我们将了解如何将 Google 和 Facebook 等外部 OAuth 提供商集成到流程中。

原文链接:www.zakariaamine.com/2018-03-01/...

相关推荐
考虑考虑34 分钟前
JDK9中的dropWhile
java·后端·java ee
想躺平的咸鱼干42 分钟前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
hqxstudying1 小时前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·1 小时前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
martinzh2 小时前
Spring AI 项目介绍
后端
Bug退退退1232 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠2 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
前端付豪2 小时前
20、用 Python + API 打造终端天气预报工具(支持城市查询、天气图标、美化输出🧊
后端·python
爱学习的小学渣2 小时前
关系型数据库
后端
武子康2 小时前
大数据-33 HBase 整体架构 HMaster HRegion
大数据·后端·hbase