核心型号 / 组件

注册客户端

A 是向授权服务器注册的客户端的表示形式。 客户端必须先向授权服务器注册,然后才能启动授权授予流,例如 或 。RegisteredClientauthorization_codeclient_credentialsspring-doc.cn

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

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

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

以下示例显示如何配置允许执行 authorization_code 授权流以请求访问令牌的 一个:RegisteredClientspring-doc.cn

RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
	.clientId("client-a")
	.clientSecret("{noop}secret")   (1)
	.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();
1 {noop}表示 Spring Security 的 NoOpPasswordEncoder 的 ID。PasswordEncoder

Spring Security 的 OAuth2 客户端支持中的相应配置为:spring-doc.cn

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

A 具有与其唯一客户端标识符关联的元数据(属性),定义如下:RegisteredClientspring-doc.cn

public class RegisteredClient implements Serializable {
	private String id;  (1)
	private String clientId;    (2)
	private Instant clientIdIssuedAt;   (3)
	private String clientSecret;    (4)
	private Instant clientSecretExpiresAt;  (5)
	private String clientName;  (6)
	private Set<ClientAuthenticationMethod> clientAuthenticationMethods;    (7)
	private Set<AuthorizationGrantType> authorizationGrantTypes;    (8)
	private Set<String> redirectUris;   (9)
	private Set<String> postLogoutRedirectUris; (10)
	private Set<String> scopes; (11)
	private ClientSettings clientSettings;  (12)
	private TokenSettings tokenSettings;    (13)

	...

}
1 id:唯一标识 的 ID。RegisteredClient
2 clientId:客户端标识符。
3 clientIdIssuedAt:客户端标识符的发布时间。
4 clientSecret:客户端的密钥。该值应使用 Spring Security 的 PasswordEncoder 进行编码。
5 clientSecretExpiresAt:客户端密钥过期的时间。
6 clientName:用于客户端的描述性名称。在某些情况下,例如在同意页面中显示客户端名称时,可能会使用该名称。
7 clientAuthenticationMethods:客户端可能使用的身份验证方法。支持的值为 、 、 、 private_key_jwt(public clients)。client_secret_basicclient_secret_postclient_secret_jwtnone
8 authorizationGrantTypes:客户端可以使用的授权授权类型。支持的值为 、 、 、 和 。authorization_codeclient_credentialsrefresh_tokenurn:ietf:params:oauth:grant-type:device_codeurn:ietf:params:oauth:grant-type:token-exchange
9 redirectUris:客户端可以在基于重定向的流中使用的已注册重定向 URI,例如 grant。authorization_code
10 postLogoutRedirectUris:客户端可用于注销的注销后重定向 URI。
11 scopes:允许客户端请求的范围 () 。
12 clientSettings:客户端的自定义设置 – 例如,需要 PKCE、需要授权同意等。
13 tokenSettings:颁发给客户端的 OAuth2 令牌的自定义设置 – 例如,访问/刷新令牌生存时间、重用刷新令牌等。

RegisteredClient存储库

它是可以注册新客户端和查询现有客户端的中心组件。 当遵循特定协议流时,其他组件会使用它,例如客户端身份验证、授权授予处理、令牌自省、动态客户端注册等。RegisteredClientRepositoryspring-doc.cn

提供的 are 和 . 该实现将实例存储在内存中,建议仅在开发和测试期间使用。 是一种 JDBC 实现,它使用 来持久化实例。RegisteredClientRepositoryInMemoryRegisteredClientRepositoryJdbcRegisteredClientRepositoryInMemoryRegisteredClientRepositoryRegisteredClientJdbcRegisteredClientRepositoryRegisteredClientJdbcOperationsspring-doc.cn

REQUIRED 组件。RegisteredClientRepository

以下示例说明如何注册 :RegisteredClientRepository@Beanspring-doc.cn

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

或者,您可以通过 OAuth2AuthorizationServerConfigurer 进行配置:RegisteredClientRepositoryspring-doc.cn

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

	http
		.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
		.with(authorizationServerConfigurer, (authorizationServer) ->
			authorizationServer
				.registeredClientRepository(registeredClientRepository)
		)
	    ...

	return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer

OAuth2授权

An 是 OAuth2 授权的表示形式,它包含与资源所有者授予客户端的授权相关的状态,或者在授权授权类型的情况下,它自己也由其自身授予。OAuth2Authorizationclient_credentialsspring-doc.cn

Spring Security 的 OAuth2 客户端支持中相应的授权模型是 OAuth2AuthorizedClient

成功完成授权授权流程后,将创建一个并关联 OAuth2AccessToken、(可选)OAuth2RefreshToken 和特定于已执行授权授权类型的其他状态。OAuth2Authorizationspring-doc.cn

与 关联的 OAuth2Token 实例会有所不同,具体取决于授权授权类型。OAuth2Authorizationspring-doc.cn

对于 OAuth2 authorization_code 授权,将关联 an 、 an 和 an (可选)。OAuth2AuthorizationCodeOAuth2AccessTokenOAuth2RefreshTokenspring-doc.cn

对于 OpenID Connect 1.0 authorization_code授权,将关联 、 OidcIdToken、 和 (可选)。OAuth2AuthorizationCodeOAuth2AccessTokenOAuth2RefreshTokenspring-doc.cn

对于 OAuth2 client_credentials 授权,仅关联 an。OAuth2AccessTokenspring-doc.cn

OAuth2Authorization其属性定义如下:spring-doc.cn

public class OAuth2Authorization implements Serializable {
	private String id;  (1)
	private String registeredClientId;  (2)
	private String principalName;   (3)
	private AuthorizationGrantType authorizationGrantType;  (4)
	private Set<String> authorizedScopes;   (5)
	private Map<Class<? extends OAuth2Token>, Token<?>> tokens; (6)
	private Map<String, Object> attributes; (7)

	...

}
1 id:唯一标识 的 ID。OAuth2Authorization
2 registeredClientId:唯一标识 RegisteredClient 的 ID。
3 principalName:资源所有者(或客户端)的主体名称。
4 authorizationGrantType: 二手的。AuthorizationGrantType
5 authorizedScopes:为客户端授权的范围。Set
6 tokens:特定于已执行授权授权类型的实例(和关联的元数据)。OAuth2Token
7 attributes:特定于已执行授权授权类型的其他属性 – 例如,经过身份验证的 、 和其他。PrincipalOAuth2AuthorizationRequest

OAuth2Authorization及其关联的实例具有固定的生命周期。 新颁发的证书处于活动状态,并在过期或失效(撤销)时变为非活动状态。 当所有关联的实例都处于非活动状态时,它 is (隐式) inactive 。 每个 都包含在 中,该 为 、 和 提供访问器。OAuth2TokenOAuth2TokenOAuth2AuthorizationOAuth2TokenOAuth2TokenOAuth2Authorization.TokenisExpired()isInvalidated()isActive()spring-doc.cn

OAuth2Authorization.Token还提供 ,它返回与 关联的声明(如果有)。getClaims()OAuth2Tokenspring-doc.cn

OAuth2AuthorizationService

它是存储新授权和查询现有授权的中心组件。 当遵循特定协议流时,其他组件会使用它,例如,客户端身份验证、授权授予处理、令牌自省、令牌吊销、动态客户端注册等。OAuth2AuthorizationServicespring-doc.cn

提供的 are 和 . 该实现将实例存储在内存中,建议仅在开发和测试期间使用。 是一种 JDBC 实现,它使用 来持久化实例。OAuth2AuthorizationServiceInMemoryOAuth2AuthorizationServiceJdbcOAuth2AuthorizationServiceInMemoryOAuth2AuthorizationServiceOAuth2AuthorizationJdbcOAuth2AuthorizationServiceOAuth2AuthorizationJdbcOperationsspring-doc.cn

它是一个 OPTIONAL 组件,默认为 .OAuth2AuthorizationServiceInMemoryOAuth2AuthorizationService

以下示例显示如何注册 :OAuth2AuthorizationService@Beanspring-doc.cn

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

或者,您可以通过 OAuth2AuthorizationServerConfigurer 进行配置:OAuth2AuthorizationServicespring-doc.cn

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

	http
		.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
		.with(authorizationServerConfigurer, (authorizationServer) ->
			authorizationServer
				.authorizationService(authorizationService)
		)
	    ...

	return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer

An 是来自 OAuth2 授权请求流的授权 “同意” (决定) 的表示形式,例如,授权,它包含资源所有者授予客户端的权限。OAuth2AuthorizationConsentauthorization_codespring-doc.cn

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

OAuth2 授权请求流完成后,将创建(或更新)一个,并将授予的权限与客户端和资源所有者相关联。OAuth2AuthorizationConsentspring-doc.cn

OAuth2AuthorizationConsent其属性定义如下:spring-doc.cn

public final class OAuth2AuthorizationConsent implements Serializable {
	private final String registeredClientId;    (1)
	private final String principalName; (2)
	private final Set<GrantedAuthority> authorities;    (3)

	...

}
1 registeredClientId:唯一标识 RegisteredClient 的 ID。
2 principalName:资源所有者的主体名称。
3 authorities:资源所有者授予客户端的权限。颁发机构可以表示范围、声明、权限、角色等。

它是存储新授权同意和查询现有授权同意的中心组件。 它主要由实现 OAuth2 授权请求流的组件使用,例如授权。OAuth2AuthorizationConsentServiceauthorization_codespring-doc.cn

提供的 are 和 . 该实现将实例存储在内存中,建议仅用于开发和测试。 是一种 JDBC 实现,它使用 来持久化实例。OAuth2AuthorizationConsentServiceInMemoryOAuth2AuthorizationConsentServiceJdbcOAuth2AuthorizationConsentServiceInMemoryOAuth2AuthorizationConsentServiceOAuth2AuthorizationConsentJdbcOAuth2AuthorizationConsentServiceOAuth2AuthorizationConsentJdbcOperationsspring-doc.cn

它是一个 OPTIONAL 组件,默认为 .OAuth2AuthorizationConsentServiceInMemoryOAuth2AuthorizationConsentService

以下示例显示如何注册 :OAuth2AuthorizationConsentService@Beanspring-doc.cn

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

或者,您可以通过 OAuth2AuthorizationServerConfigurer 进行配置:OAuth2AuthorizationConsentServicespring-doc.cn

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

	http
		.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
		.with(authorizationServerConfigurer, (authorizationServer) ->
			authorizationServer
				.authorizationConsentService(authorizationConsentService)
		)
	    ...

	return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer

OAuth2TokenContext

An 是一个上下文对象,它保存与 an 关联的信息,并由 OAuth2TokenGeneratorOAuth2TokenCustomizer 使用。OAuth2TokenContextOAuth2Tokenspring-doc.cn

OAuth2TokenContext提供以下访问器:spring-doc.cn

public interface OAuth2TokenContext extends Context {

	default RegisteredClient getRegisteredClient() ...  (1)

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

	default AuthorizationServerContext getAuthorizationServerContext() ...    (3)

	@Nullable
	default OAuth2Authorization getAuthorization() ...  (4)

	default Set<String> getAuthorizedScopes() ...   (5)

	default OAuth2TokenType getTokenType() ...  (6)

	default AuthorizationGrantType getAuthorizationGrantType() ...  (7)

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

	...

}
1 getRegisteredClient():与授权授权关联的 RegisteredClient
2 getPrincipal():资源所有者(或客户端)的实例。Authentication
3 getAuthorizationServerContext():保存 Authorization Server 运行时环境信息的 AuthorizationServerContext 对象。
4 getAuthorization():与授权授权关联的 OAuth2Authorization
5 getAuthorizedScopes():为客户端授权的范围。
6 getTokenType():要生成的。支持的值为 、 、 和 。OAuth2TokenTypecodeaccess_tokenrefresh_tokenid_token
7 getAuthorizationGrantType():与授权授权关联的。AuthorizationGrantType
8 getAuthorizationGrant():处理授权的 使用的实例。AuthenticationAuthenticationProvider

OAuth2令牌生成器

An 负责从提供的 OAuth2TokenContext 中包含的信息生成一个。OAuth2TokenGeneratorOAuth2Tokenspring-doc.cn

生成的 主要取决于 中指定的类型 。OAuth2TokenOAuth2TokenTypeOAuth2TokenContextspring-doc.cn

例如,当 for 为:valueOAuth2TokenTypespring-doc.cn

此外,生成的格式会有所不同,具体取决于 RegisteredClient 的配置。 如果格式为 (默认),则生成 a。 如果格式为 ,则生成“不透明”令牌。OAuth2AccessTokenTokenSettings.getAccessTokenFormat()OAuth2TokenFormat.SELF_CONTAINEDJwtOAuth2TokenFormat.REFERENCEspring-doc.cn

最后,如果生成的具有一组 claims 和 implements ,则可以从 OAuth2Authorization.Token.getClaims() 访问这些声明。OAuth2TokenClaimAccessorspring-doc.cn

这主要由实施授权授权处理的组件使用,例如 、 和 。OAuth2TokenGeneratorauthorization_codeclient_credentialsrefresh_tokenspring-doc.cn

提供的实现是 、 和 。 生成一个 “opaque” () 访问令牌,生成一个 ()。OAuth2AccessTokenGeneratorOAuth2RefreshTokenGeneratorJwtGeneratorOAuth2AccessTokenGeneratorOAuth2TokenFormat.REFERENCEJwtGeneratorJwtOAuth2TokenFormat.SELF_CONTAINEDspring-doc.cn

它是一个 OPTIONAL 组件,默认为 由 和 组成的 。OAuth2TokenGeneratorDelegatingOAuth2TokenGeneratorOAuth2AccessTokenGeneratorOAuth2RefreshTokenGenerator
如果已注册 a,则 a 将另外组成在 .JwtEncoder@BeanJWKSource<SecurityContext>@BeanJwtGeneratorDelegatingOAuth2TokenGenerator

这提供了极大的灵活性,因为它可以支持 和 的任何自定义令牌格式。OAuth2TokenGeneratoraccess_tokenrefresh_tokenspring-doc.cn

以下示例显示如何注册 :OAuth2TokenGenerator@Beanspring-doc.cn

@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 进行配置:OAuth2TokenGeneratorspring-doc.cn

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

	http
		.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
		.with(authorizationServerConfigurer, (authorizationServer) ->
			authorizationServer
				.tokenGenerator(tokenGenerator)
		)
	    ...

	return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer

OAuth2TokenCustomizer (OAuth2令牌自定义器)

An 提供了自定义 的属性的功能,这些属性可在提供的 OAuth2TokenContext 中访问。 OAuth2TokenGenerator 使用它来让它在生成之前自定义 的属性。OAuth2TokenCustomizerOAuth2TokenOAuth2Tokenspring-doc.cn

使用泛型类型 () 声明的功能提供了自定义 “opaque” 的声明的能力。 提供对 的访问,从而允许添加、替换和删除声明。OAuth2TokenCustomizer<OAuth2TokenClaimsContext>OAuth2TokenClaimsContextimplements OAuth2TokenContextOAuth2AccessTokenOAuth2TokenClaimsContext.getClaims()OAuth2TokenClaimsSet.Builderspring-doc.cn

以下示例显示了如何实现 an 并使用 an 配置它:OAuth2TokenCustomizer<OAuth2TokenClaimsContext>OAuth2AccessTokenGeneratorspring-doc.cn

@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

	};
}
如果未作为 提供或未通过 进行配置,则 将自动配置一个 。OAuth2TokenGenerator@BeanOAuth2AuthorizationServerConfigurerOAuth2TokenCustomizer<OAuth2TokenClaimsContext>@BeanOAuth2AccessTokenGenerator

使用泛型类型 () 声明的 API 提供了自定义 . 提供对 的访问,从而允许添加、替换和删除标头。 提供对 的访问,从而允许添加、替换和删除声明。OAuth2TokenCustomizer<JwtEncodingContext>JwtEncodingContextimplements OAuth2TokenContextJwtJwtEncodingContext.getJwsHeader()JwsHeader.BuilderJwtEncodingContext.getClaims()JwtClaimsSet.Builderspring-doc.cn

以下示例显示如何实现 an 并使用 :OAuth2TokenCustomizer<JwtEncodingContext>JwtGeneratorspring-doc.cn

@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.getJwsHeader();
		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

		}
	};
}
如果未作为 提供或未通过 进行配置,则 将自动使用 配置。OAuth2TokenGenerator@BeanOAuth2AuthorizationServerConfigurerOAuth2TokenCustomizer<JwtEncodingContext>@BeanJwtGenerator

SessionRegistry (会话注册表)

如果启用了 OpenID Connect 1.0,则实例将用于跟踪经过身份验证的会话。 它由 关联的 的默认实现 用于注册新的经过身份验证的会话SessionRegistrySessionRegistrySessionAuthenticationStrategyspring-doc.cn

如果未注册 a,则将使用默认实现。SessionRegistry@BeanSessionRegistryImpl
如果 已注册 并且是 的实例,则还应注册 ,因为它负责通知会话生命周期事件,例如,以提供删除实例的功能。SessionRegistry@BeanSessionRegistryImplHttpSessionEventPublisher@BeanSessionRegistryImplSessionDestroyedEventSessionInformation

当最终用户请求注销时,OpenID Connect 1.0 注销端点使用 查找与经过身份验证的最终用户关联的数据以执行注销。SessionRegistrySessionInformationspring-doc.cn

如果正在使用 Spring Security 的并发会话控制功能,建议注册一个以确保它在 Spring Security 的并发会话控制和 Spring 授权服务器的注销功能之间共享。SessionRegistry@Beanspring-doc.cn

以下示例显示如何注册 和 (需要):SessionRegistry@BeanHttpSessionEventPublisher@BeanSessionRegistryImplspring-doc.cn

@Bean
public SessionRegistry sessionRegistry() {
	return new SessionRegistryImpl();
}

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
	return new HttpSessionEventPublisher();
}