Spring 授权服务器核心模型/组件

时间:2022-12-06 11:34:05

Spring 授权服务器核心模型/组件

注册客户

A是向授权服务器注册的客户端的表示形式。 客户端必须先向授权服务器注册,然后才能启动授权流(如 asor)。RegisteredClientauthorization_codeclient_credentials

在客户端注册期间,将为客户端分配一个唯一的客户端标识符、(可选)一个客户端密码(取决于客户端类型)以及与它的唯一客户端标识符关联的元数据。 客户端的元数据范围可以从面向人的显示字符串(如客户端名称)到特定于协议流的项目(如有效重定向 URI 列表)。

Spring Security 的 OAuth2 客户端支持中相应的客户端注册模型是客户端注册。

客户端的主要用途是请求访问受保护的资源。 客户端首先通过向授权服务器进行身份验证并提供授权来请求访问令牌。 授权服务器对客户端和授权授权进行身份验证,如果它们有效,则颁发访问令牌。 客户端现在可以通过提供访问令牌从资源服务器请求受保护的资源。

以下示例演示如何配置允许执行authorization_code授予流以请求访问令牌的 a:​​RegisteredClient​

RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("client-a")
.clientSecret("{noop}secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("http://127.0.0.1:8080/authorized")
.scope("scope-a")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();

​{noop}​​​表示 Spring Security 的NoOpPasswordEncoder​ 的 id。​​PasswordEncoder​

Spring Security 的OAuth2 客户端支持中的相应配置是:

spring:
security:
oauth2:
client:
registration:
client-a:
provider: spring
client-id: client-a
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: "http://127.0.0.1:8080/authorized"
scope: scope-a
provider:
spring:
issuer-uri: http://localhost:9000

Ahas 具有与其唯一客户端标识符关联的元数据(属性),定义如下:​​RegisteredClient​

public class RegisteredClient implements Serializable {
private String id;
private String clientId;
private Instant clientIdIssuedAt;
private String clientSecret;
private Instant clientSecretExpiresAt;
private String clientName;
private Set<ClientAuthenticationMethod> clientAuthenticationMethods;
private Set<AuthorizationGrantType> authorizationGrantTypes;
private Set<String> redirectUris;
private Set<String> scopes;
private ClientSettings clientSettings;
private TokenSettings tokenSettings;

...

}

​id​​​:唯一标识 的 ID。​​RegisteredClient​

​clientId​​:客户端标识符。

​clientIdIssuedAt​​:发出客户端标识符的时间。

​clientSecret​​​:客户端的机密。该值应使用 Spring Security 的PasswordEncoder 进行编码。

​clientSecretExpiresAt​​:客户端密码过期的时间。

​clientName​​:用于客户端的描述性名称。该名称可能在某些情况下使用,例如在同意页中显示客户端名称时。

​clientAuthenticationMethods​​​:客户端可以使用的身份验证方法。支持的值为、、private_key_jwt​、和(公共客户端)。​​client_secret_basic​​​​client_secret_post​​​​client_secret_jwt​​​​none​

​authorizationGrantTypes​​​:客户端可以使用的授权类型​。支持的值为 、 和。​​authorization_code​​​​client_credentials​​​​refresh_token​

​redirectUris​​​:客户端可能在基于重定向的流中使用的已注册重定向 URI,例如​​,​​​授予。​​authorization_code​

​scopes​​:允许客户端请求的范围。

​clientSettings​​​:客户端的自定义设置 - 例如,需要PKCE、需要授权同意等。

​tokenSettings​​:颁发给客户端的 OAuth2 令牌的自定义设置,例如,访问/刷新令牌生存时间、重用刷新令牌等。

注册客户端存储库

这是可以注册新客户端和查询现有客户端的中心组件。 其他组件在遵循特定协议流(如客户端身份验证、授权授权处理、令牌自检、动态客户端注册等)时使用它。​​RegisteredClientRepository​

提供的实现。 该实现将实例存储在内存中,建议仅在开发期间使用,并 testing.is 通过使用持久化实例的 JDBC 实现。​​RegisteredClientRepository​​​​InMemoryRegisteredClientRepository​​​​JdbcRegisteredClientRepository​​​​InMemoryRegisteredClientRepository​​​​RegisteredClient​​​​JdbcRegisteredClientRepository​​​​RegisteredClient​​​​JdbcOperations​

这是一个必需的组件。​​RegisteredClientRepository​

以下示例演示如何注册:​​RegisteredClientRepository​​​​@Bean​

@Bean
public RegisteredClientRepository registeredClientRepository() {
List<RegisteredClient> registrations = ...
return new InMemoryRegisteredClientRepository(registrations);
}

或者,您可以通过OAuth2AuthorizationServerConfigurer进行配置:​​RegisteredClientRepository​

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);

authorizationServerConfigurer
.registeredClientRepository(registeredClientRepository);

...

return http.build();
}

当同时应用多个配置选项时很有用。​​OAuth2AuthorizationServerConfigurer​

OAuth2授权

Anis OAuth2 授权的表示形式,它包含与资源所有者授予客户端的授权相关的状态,如果是授权授权类型,则由资源所有者或自身授予​​。​​​​OAuth2Authorization​​​​client_credentials​

Spring Security 的 OAuth2 Client 支持中的相应授权模型是OAuth2AuthorizedClient。

成功完成授权授权流后,anis 创建并关联 OAuth2AccessToken、(可选)OAuth2RefreshToken 以及特定于已执行授权类型的其他状态。​​OAuth2Authorization​

与 anvary 关联的OAuth2Token实例,具体取决于授权授权类型。​​OAuth2Authorization​

对于 OAuth2authorization_code授权,将关联 an、an 和 an(可选)。​​OAuth2AuthorizationCode​​​​OAuth2AccessToken​​​​OAuth2RefreshToken​

对于 OpenID Connect 1.0authorization_code授予,将关联 an、OidcIdToken、an 和 (可选)。​​OAuth2AuthorizationCode​​​​OAuth2AccessToken​​​​OAuth2RefreshToken​

对于 OAuth2client_credentials 授权,只有 anis 关联。​​OAuth2AccessToken​

​OAuth2Authorization​​其属性定义如下:

public class OAuth2Authorization implements Serializable {
private String id;
private String registeredClientId;
private String principalName;
private AuthorizationGrantType authorizationGrantType;
private Set<String> authorizedScopes;
private Map<Class<? extends OAuth2Token>, Token<?>> tokens;
private Map<String, Object> attributes;

...

}

​id​​​:唯一标识 的 ID。​​OAuth2Authorization​

​registeredClientId​​​:唯一标识已注册客户端的 ID。

​principalName​​:资源所有者(或客户端)的主体名称。

​authorizationGrantType​​​:已使用。​​AuthorizationGrantType​

​authorizedScopes​​​:为客户端授权的范围。​​Set​

​tokens​​​:特定于已执行授权类型的实例(和关联的元数据)。​​OAuth2Token​

​attributes​​​:特定于已执行授权类型的其他属性,例如,经过身份验证的 / 和其他属性。​​Principal​​​​OAuth2AuthorizationRequest​

​OAuth2Authorization​​及其关联实例具有固定的生命周期。 新发行的 dis 活动状态,并在过期或失效(吊销)时变为非活动状态。 当所有关联的实例都处于非活动状态时,Theis(隐式)处于非活动状态。 Eachis 保存在 an 中,它为 、 和 提供访问器。​​OAuth2Token​​​​OAuth2Token​​​​OAuth2Authorization​​​​OAuth2Token​​​​OAuth2Token​​​​OAuth2Authorization.Token​​​​isExpired()​​​​isInvalidated()​​​​isActive()​

​OAuth2Authorization.Token​​还提供,其返回与声明(如果有的话)相关联的声明。​​getClaims()​​​​OAuth2Token​

OAuth2授权服务

这是存储新授权和查询现有授权的中心组件。 其他组件在遵循特定协议流时使用它,例如,客户端身份验证、授权处理、令牌自检、令牌吊销、动态客户端注册等。​​OAuth2AuthorizationService​

提供的实现。 该实现将实例存储在内存中,建议仅在开发期间使用,并 testing.is 通过使用持久化实例的 JDBC 实现。​​OAuth2AuthorizationService​​​​InMemoryOAuth2AuthorizationService​​​​JdbcOAuth2AuthorizationService​​​​InMemoryOAuth2AuthorizationService​​​​OAuth2Authorization​​​​JdbcOAuth2AuthorizationService​​​​OAuth2Authorization​​​​JdbcOperations​

The is an OPTIONAL component and defaults to . ​​OAuth2AuthorizationService​​​​InMemoryOAuth2AuthorizationService​

The following example shows how to register an :​​OAuth2AuthorizationService​​​​@Bean​

@Bean
public OAuth2AuthorizationService authorizationService() {
return new InMemoryOAuth2AuthorizationService();
}

Alternatively, you can configure the through the OAuth2AuthorizationServerConfigurer:​​OAuth2AuthorizationService​

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);

authorizationServerConfigurer
.authorizationService(authorizationService);

...

return http.build();
}

当同时应用多个配置选项时很有用。​​OAuth2AuthorizationServerConfigurer​

OAuth2授权同意

Anis 来自OAuth2 授权请求流的授权“同意”(决策)的表示形式,例如,授予,其中包含资源所有者授予客户端的权限。​​OAuth2AuthorizationConsent​​​​authorization_code​

授权访问客户端时,资源所有者只能授予客户端请求的权限子集。 典型的用例是授权流,其中客户端请求范围,资源所有者授予(或拒绝)对请求的范围的访问权限。​​authorization_code​

完成 OAuth2 授权请求流后,anis 创建(或更新)授予的权限并将其与客户端和资源所有者相关联。​​OAuth2AuthorizationConsent​

​OAuth2AuthorizationConsent​​其属性定义如下:

public final class OAuth2AuthorizationConsent implements Serializable {
private final String registeredClientId;
private final String principalName;
private final Set<GrantedAuthority> authorities;

...

}

​registeredClientId​​​:唯一标识已注册客户端的 ID。

​principalName​​:资源所有者的主体名称。

​authorities​​:资源所有者授予客户端的权限。颁发机构可以表示范围、声明、权限、角色等。

OAuth2授权同意服务

这是存储新授权同意和查询现有授权同意的中心组件。 它主要由实现 OAuth2 授权请求流的组件使用,例如授予。​​OAuth2AuthorizationConsentService​​​​authorization_code​

提供的实现。 该实现将实例存储在内存中,建议仅用于开发和 testing.is JDBC 实现,该实现通过使用持久化实例。​​OAuth2AuthorizationConsentService​​​​InMemoryOAuth2AuthorizationConsentService​​​​JdbcOAuth2AuthorizationConsentService​​​​InMemoryOAuth2AuthorizationConsentService​​​​OAuth2AuthorizationConsent​​​​JdbcOAuth2AuthorizationConsentService​​​​OAuth2AuthorizationConsent​​​​JdbcOperations​

这是一个可选组件,默认为。​​OAuth2AuthorizationConsentService​​​​InMemoryOAuth2AuthorizationConsentService​

以下示例演示如何注册:​​OAuth2AuthorizationConsentService​​​​@Bean​

@Bean
public OAuth2AuthorizationConsentService authorizationConsentService() {
return new InMemoryOAuth2AuthorizationConsentService();
}

或者,您可以通过OAuth2AuthorizationServerConfigurer进行配置:​​OAuth2AuthorizationConsentService​

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);

authorizationServerConfigurer
.authorizationConsentService(authorizationConsentService);

...

return http.build();
}

当同时应用多个配置选项时很有用。​​OAuth2AuthorizationServerConfigurer​

OAuth2TokenContext

Anis 保存与 anand 关联的信息的上下文对象由 OAuth2TokenGenerator 和OAuth2TokenCustomizer 使用。​​OAuth2TokenContext​​​​OAuth2Token​

​OAuth2TokenContext​​提供以下访问器:

public interface OAuth2TokenContext extends Context {

default RegisteredClient getRegisteredClient() ...

default <T extends Authentication> T getPrincipal() ...

default AuthorizationServerContext getAuthorizationServerContext() ...

@Nullable
default OAuth2Authorization getAuthorization() ...

default Set<String> getAuthorizedScopes() ...

default OAuth2TokenType getTokenType() ...

default AuthorizationGrantType getAuthorizationGrantType() ...

default <T extends Authentication> T getAuthorizationGrant() ...

...

}

​getRegisteredClient()​​​:与授权授予关联的注册客户端。

​getPrincipal()​​​:资源所有者(或客户端)的实例。​​Authentication​

​getAuthorizationServerContext()​​​:保存授权服务器运行时环境信息的授权服务器上下文对象。

​getAuthorization()​​​:与授权授予关联的OAuth2Authorization。

​getAuthorizedScopes()​​:为客户端授权的范围。

​getTokenType()​​​:生成。支持的值为,,,和。​​OAuth2TokenType​​​​code​​​​access_token​​​​refresh_token​​​​id_token​

​getAuthorizationGrantType()​​​:与授权授予相关联。​​AuthorizationGrantType​

​getAuthorizationGrant()​​​:处理授权授权使用的实例。​​Authentication​​​​AuthenticationProvider​

OAuth2TokenGenerator

Anis 负责从提供的OAuth2TokenContext 中包含的信息生成信息。​​OAuth2TokenGenerator​​​​OAuth2Token​

生成的主要取决于类型中指定的。​​OAuth2Token​​​​OAuth2TokenType​​​​OAuth2TokenContext​

例如,当福里斯:​​value​​​​OAuth2TokenType​

  • ​code​​,然后生成。OAuth2AuthorizationCode
  • ​access_token​​,然后生成。OAuth2AccessToken
  • ​refresh_token​​,然后生成。OAuth2RefreshToken
  • ​id_token​​,然后生成。OidcIdToken

此外,生成的格式会有所不同,具体取决于已注册客户端的配置。 如果格式为(默认值),则生成 ais 。 如果格式为,则会生成“不透明”令牌。​​OAuth2AccessToken​​​​TokenSettings.getAccessTokenFormat()​​​​OAuth2TokenFormat.SELF_CONTAINED​​​​Jwt​​​​OAuth2TokenFormat.REFERENCE​

最后,如果生成的声明和实现有一组,则可以从OAuth2Authorization.Token.getClaims()访问这些声明。​​OAuth2Token​​​​ClaimAccessor​

主要由实现授权授权处理的组件使用,,,​​OAuth2TokenGenerator​​​​authorization_code​​​​client_credentials​​​​refresh_token​

提供的实现是、和。 生成一个“不透明”() 访问令牌,并生成 a()。​​OAuth2AccessTokenGenerator​​​​OAuth2RefreshTokenGenerator​​​​JwtGenerator​​​​OAuth2AccessTokenGenerator​​​​OAuth2TokenFormat.REFERENCE​​​​JwtGenerator​​​​Jwt​​​​OAuth2TokenFormat.SELF_CONTAINED​

这是一个可选组件,默认由 anand 组成。​​OAuth2TokenGenerator​​​​DelegatingOAuth2TokenGenerator​​​​OAuth2AccessTokenGenerator​​​​OAuth2RefreshTokenGenerator​

如果aoris注册,则ais另外组成在。​​JwtEncoder​​​​@Bean​​​​JWKSource<SecurityContext>​​​​@Bean​​​​JwtGenerator​​​​DelegatingOAuth2TokenGenerator​

这提供了极大的灵活性,因为它可以支持任何自定义令牌格式。​​OAuth2TokenGenerator​​​​access_token​​​​refresh_token​

以下示例演示如何注册:​​OAuth2TokenGenerator​​​​@Bean​

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

或者,您可以通过OAuth2AuthorizationServerConfigurer进行配置:​​OAuth2TokenGenerator​

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);

authorizationServerConfigurer
.tokenGenerator(tokenGenerator);

...

return http.build();
}

当同时应用多个配置选项时很有用。​​OAuth2AuthorizationServerConfigurer​

OAuth2TokenCustomizer

An提供了自定义属性的功能,这些属性可在提供的OAuth2TokenContext中访问。 它由OAuth2TokenGenerator使用,以使其在生成之前自定义属性。​​OAuth2TokenCustomizer​​​​OAuth2Token​​​​OAuth2Token​

使用泛型类型 of() 声明提供了自定义声明“不透明”的能力。提供对 的访问,允许添加、替换和删除声明。​​OAuth2TokenCustomizer<OAuth2TokenClaimsContext>​​​​OAuth2TokenClaimsContext​​​​implements OAuth2TokenContext​​​​OAuth2AccessToken​​​​OAuth2TokenClaimsContext.getClaims()​​​​OAuth2TokenClaimsSet.Builder​

以下示例演示如何实现 anand 配置它:​​OAuth2TokenCustomizer<OAuth2TokenClaimsContext>​​​​OAuth2AccessTokenGenerator​

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer());
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

@Bean
public OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer() {
return context -> {
OAuth2TokenClaimsSet.Builder claims = context.getClaims();
// Customize claims

};
}

如果未提供 aor 未通过配置,则将自动配置一个。​​OAuth2TokenGenerator​​​​@Bean​​​​OAuth2AuthorizationServerConfigurer​​​​OAuth2TokenCustomizer<OAuth2TokenClaimsContext>​​​​@Bean​​​​OAuth2AccessTokenGenerator​

使用泛型类型 of() 声明提供了自定义标头和声明的能力 a。提供对 的访问,允许添加、替换和删除标头。提供对 的访问,允许添加、替换和删除声明。​​OAuth2TokenCustomizer<JwtEncodingContext>​​​​JwtEncodingContext​​​​implements OAuth2TokenContext​​​​Jwt​​​​JwtEncodingContext.getHeaders()​​​​JwsHeader.Builder​​​​JwtEncodingContext.getClaims()​​​​JwtClaimsSet.Builder​

以下示例演示如何使用 aand 对其进行配置:​​OAuth2TokenCustomizer<JwtEncodingContext>​​​​JwtGenerator​

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
jwtGenerator.setJwtCustomizer(jwtCustomizer());
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
return context -> {
JwsHeader.Builder headers = context.getHeaders();
JwtClaimsSet.Builder claims = context.getClaims();
if (context.getTokenType().equals(OAuth2TokenType.ACCESS_TOKEN)) {
// Customize headers/claims for access_token

} else if (context.getTokenType().getValue().equals(OidcParameterNames.ID_TOKEN)) {
// Customize headers/claims for id_token

}
};
}

如果未提供 aor 未通过 配置,则将自动配置一个。​​OAuth2TokenGenerator​​​​@Bean​​​​OAuth2AuthorizationServerConfigurer​​​​OAuth2TokenCustomizer<JwtEncodingContext>​​​​@Bean​​​​JwtGenerator​

有关如何自定义 ID 令牌​的示例,请参阅指南操作方法:自定义 OpenID Connect 1.0 用户信息响应。