[译]在 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/...

相关推荐
杨运交25 分钟前
[069][公共模块]Spring Boot 全局异常处理与参数校验实战(下):校验异常精细化处理与 WebFlux 适配
java·spring boot·后端
Raas1001 小时前
MAI Gateway(魔芋企业级AI网关)对比分析:AI网关和OpenRouter区别?企业级能力差距一览
java·服务器·网络·人工智能·gateway·ai网关·mai gateway
Andya_net1 小时前
Spring Boot | 条件注解完全指南:从 @Conditional 到 @ConditionalOnExpression 的原理、实践与避坑
spring boot·后端·python
APItesterCris1 小时前
告别人工盯品!借助 Open‑Claw 快速搭建电商商品全自动监控与数据分析系统(完整实操代码)
java·大数据·前端·数据库
青山木1 小时前
Hot 100 --- 跳跃游戏 II
java·数据结构·算法·leetcode·贪心算法
ly76891 小时前
Spring 中的 @Configuration 与 @Component 差异:为何代理时机决定 Bean 生命周期行为
java·后端·spring·注解·代理·bean生命周期
qq_452396231 小时前
第十二篇:《数据采集:Grafana Alloy、Fluent Bit、Vector 的选型与配置》
java·贪心算法·grafana
明月_清风1 小时前
字符串匹配四大经典算法:BF、RK、BM、KMP 到底有什么区别?
后端·算法
卷无止境1 小时前
测试全绿,功能能跑,代码却烂到没法上线:AI编程助手留下的十个坑
后端·python
珍珠先生1 小时前
P16 · IDEA 启动报错:找不到或无法加载主类
java