对于最新的稳定版本,请使用 Spring Authorization Server 1.4.0spring-doc.cadn.net.cn

核心型号 / 组件

注册客户端

一个RegisteredClient是向授权服务器注册的客户端的表示形式。 客户端必须先向授权服务器注册,然后才能启动授权授予流,例如authorization_codeclient_credentials.spring-doc.cadn.net.cn

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

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

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

以下示例显示如何配置RegisteredClient允许执行 authorization_code Grant 流来请求访问令牌:spring-doc.cadn.net.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}表示PasswordEncoderid 的 Spring Security 的 NoOpPasswordEncoder

Spring Security 的 OAuth2 客户端支持中的相应配置为:spring-doc.cadn.net.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

一个RegisteredClient具有与其唯一客户端标识符关联的元数据(属性),定义如下:spring-doc.cadn.net.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:唯一标识RegisteredClient.
2 clientId:客户端标识符。
3 clientIdIssuedAt:客户端标识符的发布时间。
4 clientSecret:客户端的密钥。该值应使用 Spring Security 的 PasswordEncoder 进行编码。
5 clientSecretExpiresAt:客户端密钥过期的时间。
6 clientName:用于客户端的描述性名称。在某些情况下,例如在同意页面中显示客户端名称时,可能会使用该名称。
7 clientAuthenticationMethods:客户端可能使用的身份验证方法。支持的值为client_secret_basic,client_secret_post,private_key_jwt,client_secret_jwtnone (公共客户端)。
8 authorizationGrantTypes:客户端可以使用的授权授权类型。支持的值为authorization_code,client_credentials,refresh_token,urn:ietf:params:oauth:grant-type:device_codeurn:ietf:params:oauth:grant-type:token-exchange.
9 redirectUris:客户端可以在基于重定向的流中使用的已注册重定向 URI,例如,authorization_code授予。
10 postLogoutRedirectUris:客户端可用于注销的注销后重定向 URI。
11 scopes:允许客户端请求的范围 () 。
12 clientSettings:客户端的自定义设置 – 例如,需要 PKCE、需要授权同意等。
13 tokenSettings:颁发给客户端的 OAuth2 令牌的自定义设置 – 例如,访问/刷新令牌生存时间、重用刷新令牌等。

RegisteredClient存储库

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

提供的RegisteredClientRepositoryInMemoryRegisteredClientRepositoryJdbcRegisteredClientRepository. 这InMemoryRegisteredClientRepository实现存储RegisteredClient实例,建议仅在开发和测试期间使用。JdbcRegisteredClientRepository是一个持续存在的 JDBC 实现RegisteredClient实例JdbcOperations.spring-doc.cadn.net.cn

RegisteredClientRepositoryREQUIRED 组件。

以下示例演示如何注册RegisteredClientRepository @Bean:spring-doc.cadn.net.cn

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

或者,您也可以配置RegisteredClientRepository通过OAuth2AuthorizationServerConfigurer:spring-doc.cadn.net.cn

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

	authorizationServerConfigurer
		.registeredClientRepository(registeredClientRepository);

	...

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

OAuth2授权

OAuth2Authorization是 OAuth2 授权的表示形式,它包含与授予客户端的授权相关的状态,由资源所有者或自身(如果是client_credentials授权授权类型。spring-doc.cadn.net.cn

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

成功完成授权授予流程后,OAuth2Authorization创建并关联OAuth2AccessToken、 (可选)OAuth2RefreshToken以及特定于已执行授权授权类型的其他状态。spring-doc.cadn.net.cn

OAuth2Token实例与OAuth2Authorization根据授权授权类型而有所不同。spring-doc.cadn.net.cn

对于 OAuth2 authorization_code 授权,一个OAuth2AuthorizationCodeOAuth2AccessToken和 (可选)OAuth2RefreshToken关联。spring-doc.cadn.net.cn

对于 OpenID Connect 1.0 authorization_code授权,需要OAuth2AuthorizationCodeOidcIdTokenOAuth2AccessToken和 (可选)OAuth2RefreshToken关联。spring-doc.cadn.net.cn

对于 OAuth2 client_credentials 授权,只有OAuth2AccessToken关联。spring-doc.cadn.net.cn

OAuth2Authorization其属性定义如下:spring-doc.cadn.net.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:唯一标识OAuth2Authorization.
2 registeredClientId:唯一标识 RegisteredClient 的 ID。
3 principalName:资源所有者(或客户端)的主体名称。
4 authorizationGrantType:这AuthorizationGrantType使用。
5 authorizedScopes:这Set为客户端授权的范围。
6 tokens:这OAuth2Token实例(和关联的元数据)特定于已执行的授权授权类型。
7 attributes:特定于已执行授权授权类型的附加属性 – 例如,已验证的Principal,OAuth2AuthorizationRequest等。

OAuth2Authorization及其关联的OAuth2Token实例具有固定的生命周期。 新发行的OAuth2Token处于活动状态,并在过期或失效(吊销)时变为非活动状态。 这OAuth2Authorization在全部关联的OAuth2Token实例处于非活动状态。 每OAuth2Token保存在OAuth2Authorization.Token,它为isExpired(),isInvalidated()isActive().spring-doc.cadn.net.cn

OAuth2Authorization.Token还提供getClaims(),这将返回与OAuth2Token.spring-doc.cadn.net.cn

OAuth2AuthorizationService

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

提供的OAuth2AuthorizationServiceInMemoryOAuth2AuthorizationServiceJdbcOAuth2AuthorizationService. 这InMemoryOAuth2AuthorizationService实现存储OAuth2Authorization实例,建议仅在开发和测试期间使用。JdbcOAuth2AuthorizationService是一个持续存在的 JDBC 实现OAuth2Authorization实例JdbcOperations.spring-doc.cadn.net.cn

OAuth2AuthorizationServiceOPTIONAL 组件,默认为InMemoryOAuth2AuthorizationService.

以下示例演示如何注册OAuth2AuthorizationService @Bean:spring-doc.cadn.net.cn

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

或者,您也可以配置OAuth2AuthorizationService通过OAuth2AuthorizationServerConfigurer:spring-doc.cadn.net.cn

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

	authorizationServerConfigurer
		.authorizationService(authorizationService);

	...

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

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

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

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

OAuth2AuthorizationConsent其属性定义如下:spring-doc.cadn.net.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:资源所有者授予客户端的权限。颁发机构可以表示范围、声明、权限、角色等。

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

提供的OAuth2AuthorizationConsentServiceInMemoryOAuth2AuthorizationConsentServiceJdbcOAuth2AuthorizationConsentService. 这InMemoryOAuth2AuthorizationConsentService实现存储OAuth2AuthorizationConsent实例,建议仅用于开发和测试。JdbcOAuth2AuthorizationConsentService是一个持续存在的 JDBC 实现OAuth2AuthorizationConsent实例JdbcOperations.spring-doc.cadn.net.cn

OAuth2AuthorizationConsentServiceOPTIONAL 组件,默认为InMemoryOAuth2AuthorizationConsentService.

以下示例演示如何注册OAuth2AuthorizationConsentService @Bean:spring-doc.cadn.net.cn

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

或者,您也可以配置OAuth2AuthorizationConsentService通过OAuth2AuthorizationServerConfigurer:spring-doc.cadn.net.cn

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

	authorizationServerConfigurer
		.authorizationConsentService(authorizationConsentService);

	...

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

OAuth2TokenContext

OAuth2TokenContext是一个上下文对象,其中包含与OAuth2Token并由 OAuth2TokenGeneratorOAuth2TokenCustomizer 使用。spring-doc.cadn.net.cn

OAuth2TokenContext提供以下访问器:spring-doc.cadn.net.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():这AuthorizationServerContext保存 Authorization Server 运行时环境信息的对象。
4 getAuthorization():与授权授权关联的 OAuth2Authorization
5 getAuthorizedScopes():为客户端授权的范围。
6 getTokenType():这OAuth2TokenType生成。支持的值为code,access_token,refresh_tokenid_token.
7 getAuthorizationGrantType():这AuthorizationGrantType与授权授权相关联。
8 getAuthorizationGrant():这Authentication实例AuthenticationProvider处理授权。

OAuth2令牌生成器

OAuth2TokenGenerator负责生成OAuth2Token从提供的 OAuth2TokenContext 中包含的信息中。spring-doc.cadn.net.cn

OAuth2Token生成主要取决于OAuth2TokenTypeOAuth2TokenContext.spring-doc.cadn.net.cn

例如,当valueOAuth2TokenType是:spring-doc.cadn.net.cn

此外,生成的OAuth2AccessTokenTokenSettings.getAccessTokenFormat()RegisteredClient 配置。 如果格式为OAuth2TokenFormat.SELF_CONTAINED(默认值),则Jwt生成。 如果格式为OAuth2TokenFormat.REFERENCE,则会生成一个 “opaque” 令牌。spring-doc.cadn.net.cn

最后,如果生成的OAuth2Token具有一组声明和实现ClaimAccessor,则可以从 OAuth2Authorization.Token.getClaims() 访问声明。spring-doc.cadn.net.cn

OAuth2TokenGenerator主要由实现授权授权处理的组件使用,例如authorization_code,client_credentialsrefresh_token.spring-doc.cadn.net.cn

提供的实现包括OAuth2AccessTokenGenerator,OAuth2RefreshTokenGeneratorJwtGenerator. 这OAuth2AccessTokenGenerator生成一个 “opaque” (OAuth2TokenFormat.REFERENCE) 访问令牌,而JwtGenerator生成一个Jwt (OAuth2TokenFormat.SELF_CONTAINED).spring-doc.cadn.net.cn

OAuth2TokenGeneratorOPTIONAL 组件,默认为DelegatingOAuth2TokenGeneratorOAuth2AccessTokenGeneratorOAuth2RefreshTokenGenerator.
如果JwtEncoder @BeanJWKSource<SecurityContext> @Bean已注册,则JwtGenerator还包含在DelegatingOAuth2TokenGenerator.

OAuth2TokenGenerator提供极大的灵活性,因为它可以支持任何自定义令牌格式access_tokenrefresh_token.spring-doc.cadn.net.cn

以下示例演示如何注册OAuth2TokenGenerator @Bean:spring-doc.cadn.net.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);
}

或者,您也可以配置OAuth2TokenGenerator通过OAuth2AuthorizationServerConfigurer:spring-doc.cadn.net.cn

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

	authorizationServerConfigurer
		.tokenGenerator(tokenGenerator);

	...

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

OAuth2TokenCustomizer (OAuth2令牌自定义器)

OAuth2TokenCustomizer提供自定义OAuth2Token,这些函数可以在提供的 OAuth2TokenContext 中访问。 OAuth2TokenGenerator 使用它来自定义OAuth2Token在生成之前。spring-doc.cadn.net.cn

OAuth2TokenCustomizer<OAuth2TokenClaimsContext>使用泛型类型OAuth2TokenClaimsContext (implements OAuth2TokenContext) 提供了自定义 “opaque” 声明的功能OAuth2AccessToken.OAuth2TokenClaimsContext.getClaims()提供对OAuth2TokenClaimsSet.Builder,允许添加、替换和删除声明。spring-doc.cadn.net.cn

以下示例展示了如何实现OAuth2TokenCustomizer<OAuth2TokenClaimsContext>并使用OAuth2AccessTokenGenerator:spring-doc.cadn.net.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不作为@Bean或未通过OAuth2AuthorizationServerConfigurerOAuth2TokenCustomizer<OAuth2TokenClaimsContext> @Bean将自动配置一个OAuth2AccessTokenGenerator.

OAuth2TokenCustomizer<JwtEncodingContext>使用泛型类型JwtEncodingContext (implements OAuth2TokenContext) 提供了自定义Jwt.JwtEncodingContext.getJwsHeader()提供对JwsHeader.Builder,允许添加、替换和删除标头。JwtEncodingContext.getClaims()提供对JwtClaimsSet.Builder,允许添加、替换和删除声明。spring-doc.cadn.net.cn

以下示例展示了如何实现OAuth2TokenCustomizer<JwtEncodingContext>并使用JwtGenerator:spring-doc.cadn.net.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不作为@Bean或未通过OAuth2AuthorizationServerConfigurerOAuth2TokenCustomizer<JwtEncodingContext> @Bean将自动配置一个JwtGenerator.
有关演示如何自定义 ID 令牌的示例,请参阅指南作方法:自定义 OpenID Connect 1.0 UserInfo 响应

SessionRegistry (会话注册表)

如果启用了 OpenID Connect 1.0,则SessionRegistry实例用于跟踪已验证的会话。 这SessionRegistrySessionAuthenticationStrategyOAuth2 授权端点相关联,用于注册新的经过身份验证的会话。spring-doc.cadn.net.cn

如果SessionRegistry @Bean未注册,则默认实现SessionRegistryImpl将被使用。
如果SessionRegistry @Bean已注册,并且是SessionRegistryImpl一个HttpSessionEventPublisher @Bean 还应进行注册,因为它负责通知SessionRegistryImpl会话生命周期事件,例如SessionDestroyedEvent,以提供删除SessionInformation实例。

当最终用户请求注销时,OpenID Connect 1.0 注销终端节点使用SessionRegistry要查找SessionInformation与经过身份验证的最终用户关联以执行注销。spring-doc.cadn.net.cn

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

以下示例演示如何注册SessionRegistry @BeanHttpSessionEventPublisher @Bean(需要SessionRegistryImpl):spring-doc.cadn.net.cn

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

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