12.3。OAuth 2.0资源服务器
Spring Security支持使用两种形式的OAuth 2.0 Bearer Tokens来保护端点:
- JWT
- Opaque Tokens
在应用程序将其权限管理委派给授权服务器(例如Okta或Ping Identity)的情况下,这很方便。资源服务器可以咨询该授权服务器以授权请求。
本节详细介绍了Spring Security如何提供对OAuth 2.0 Bearer Token的支持。
Spring Security存储库中提供了JWT和Opaque Tokens的工作样本。
让我们看一下承载令牌认证在Spring Security中如何工作。首先,我们看到,就像基本身份验证一样,WWW-Authenticate header被发送回未经身份验证的客户端。
图14. Sending WWW-Authenticate Header
上图建立在我们的SecurityFilterChain图表之上。
- 首先,用户向未经授权的资源发出未经身份验证的请求。
- Spring Security的FilterSecurityInterceptor表示通过抛出AccessDeniedException拒绝了未经身份验证的请求。
- 由于用户未通过身份验证,因此ExceptionTranslationFilter会启动“开始身份验证”。 配置的AuthenticationEntryPoint是BearerTokenAuthenticationEntryPoint的实例,该实例发送WWW-Authenticate 请求头。 RequestCache通常是一个NullRequestCache,它不保存请求,因为客户端能够重播它最初请求的请求。
当客户端收到WWW-Authenticate: Bearer 请求头时,它知道应该使用承载令牌重试。以下是正在处理的承载令牌的流程。
图15.验证承载令牌
该图基于我们的SecurityFilterChain图。
- 当用户提交其承载令牌时,BearerTokenAuthenticationFilter通过从HttpServletRequest中提取令牌来创建BearerTokenAuthenticationToken,这是一种身份验证类型。
- 接下来,将HttpServletRequest传递到AuthenticationManagerResolver,后者选择AuthenticationManager。 BearerTokenAuthenticationToken传递到AuthenticationManager进行身份验证。 AuthenticationManager外观的详细信息取决于您是否配置了JWT或opaque token.。
- 如果身份验证失败,则失败
- SecurityContextHolder已清除。
- AuthenticationEntryPoint被调用以触发WWW-Authenticate 请求头再次发送。
- 如果身份验证成功,则为成功。
-
身份验证是在SecurityContextHolder上设置的。
-
BearerTokenAuthenticationFilter调用FilterChain.doFilter(request,response)继续进行其余的应用程序逻辑。
-
12.3.1。JWT的最小依赖项
大多数资源服务器支持被收集到spring-security-oauth2-resource-server中。但是,对解码和验证JWT的支持在spring-security-oauth2-jose中,这意味着为了有一个支持jwt编码的承载令牌的工作资源服务器,这两者都是必需的。
12.3.2。JWT的最小配置
使用Spring Boot时,将应用程序配置为资源服务器包括两个基本步骤。首先,包括所需的依赖关系,其次,指示授权服务器的位置。
指定授权服务器
在Spring Boot应用程序中,要指定要使用的授权服务器,只需执行以下操作:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://idp.example.com/issuer
其中https://idp.example.com/issuer是授权服务器将颁发的JWT令牌的iss声明中包含的值。 资源服务器将使用此属性进行进一步的自我配置,发现授权服务器的公钥,然后验证传入的JWT。
要使用该issuer-uri属性,它也必须是真实的一个https://idp.example.com/issuer/.well-known/openid-configuration,https://idp.example.com/.well-known/openid-configuration/issuer或者https://idp.example.com/.well-known/oauth-authorization-server/issuer是授权服务器支持的端点。此endpoint也称为提供者配endpoint或授权服务器元数据endpoint。
就是这样!
启动期望
使用此属性和这些依赖关系时,资源服务器将自动配置自身以验证JWT编码的承载令牌。
它通过确定性的启动过程来实现:
-
命中提供者配置或授权服务器元数据端点,处理jwks url属性的响应
-
配置验证策略以查询jwks_url有效的公共密钥
-
配置验证策略以针对验证每个JWT的iss声明https://idp.example.com。
此过程的结果是,授权服务器必须启动并接收请求,才能成功启动资源服务器。
如果在资源服务器查询授权服务器时授权服务器已关闭(给出适当的超时),则启动将失败。
运行时期望
应用程序启动后,资源服务器将尝试处理任何包含Authorization: Bearer标头的请求:
GET / HTTP/1.1
Authorization: Bearer some-token-value # Resource Server will process this
只要指示了此方案,资源服务器就会尝试根据Bearer Token规范处理请求。
给定格式正确的JWT,资源服务器将:
-
根据启动期间从jwks_url端点获取并与JWT匹配的公钥验证其签名
-
验证JWT的时间戳exp和nbf时间戳以及JWT的iss声明,并
-
将每个范围映射到具有前缀SCOPE_的权限。
当授权服务器提供新的密钥时,Spring Security将自动旋转用于验证JWT的密钥。
默认情况下,生成的Authentication#getPrincipal是Spring Security Jwt对象,并且Authentication#getName映射到JWT的sub属性(如果存在)。
从这里,考虑跳到:
-
JWT身份验证如何工作
-
如何在不将资源服务器启动绑定到授权服务器的可用性的情况下进行配置
-
如何在没有Spring Boot的情况下进行配置
12.3.3。JWT身份验证如何工作
接下来,让我们看看Spring Security 在基于servlet的应用程序中用来支持JWT身份验证的体系结构组件,就像我们刚刚看到的那样。
JwtAuthenticationProvider是一种AuthenticationProvider利用JwtDecoder和JwtAuthenticationConverter验证JWT的实现。
让我们看一下JwtAuthenticationProviderSpring Security中的工作方式。该图详细说明了AuthenticationManager从读取承载令牌中获取的数字的工作方式。
图16. JwtAuthenticationProvider用法
-
The authentication Filter从读取承载令牌开始,将BearerTokenAuthenticationToken传递给由ProviderManager实现的AuthenticationManager。
-
ProviderManager配置为使用JwtAuthenticationProvider类型的AuthenticationProvider。
-
JwtAuthenticationProvider使用JwtDecoder对Jwt进行解码、验证和验证。
-
然后,JwtAuthenticationProvider使用JwtAuthenticationConverter将Jwt转换为已授予的权限集合。
-
当身份验证成功时,返回的身份验证类型为JwtAuthenticationToken,其主体是配置的JwtDecoder返回的Jwt。最终,身份验证过滤器将在securitycontexts上设置返回的JwtAuthenticationToken。