此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Authorization Server 1.4.0! |
核心型号 / 组件
注册客户端
A 是向授权服务器注册的客户端的表示形式。
客户端必须先向授权服务器注册,然后才能启动授权授予流,例如 或 。RegisteredClient
authorization_code
client_credentials
在客户端注册期间,将为客户端分配一个唯一的客户端标识符、(可选)客户端密钥(取决于客户端类型)以及与客户端唯一标识符关联的元数据。 客户端的元数据范围可以从面向人的显示字符串(例如客户端名称)到特定于协议流的项目(例如有效重定向 URI 列表)。
Spring Security 的 OAuth2 客户端支持中相应的客户端注册模型是ClientRegistration。 |
客户端的主要用途是请求访问受保护的资源。 客户端首先通过向授权服务器进行身份验证并提供授权来请求访问令牌。 授权服务器对客户端和授权授权进行身份验证,如果它们有效,则颁发访问令牌。 客户端现在可以通过提供访问令牌从资源服务器请求受保护的资源。
以下示例显示如何配置允许执行 authorization_code 授权流以请求访问令牌的 一个:RegisteredClient
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:
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 具有与其唯一客户端标识符关联的元数据(属性),定义如下:RegisteredClient
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_basic client_secret_post client_secret_jwt none |
8 | authorizationGrantTypes :客户端可以使用的授权授权类型。支持的值为 、 、 、 和 。authorization_code client_credentials refresh_token urn:ietf:params:oauth:grant-type:device_code urn: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存储库
它是可以注册新客户端和查询现有客户端的中心组件。
当遵循特定协议流时,其他组件会使用它,例如客户端身份验证、授权授予处理、令牌自省、动态客户端注册等。RegisteredClientRepository
提供的 are 和 .
该实现将实例存储在内存中,建议仅在开发和测试期间使用。 是一种 JDBC 实现,它使用 来持久化实例。RegisteredClientRepository
InMemoryRegisteredClientRepository
JdbcRegisteredClientRepository
InMemoryRegisteredClientRepository
RegisteredClient
JdbcRegisteredClientRepository
RegisteredClient
JdbcOperations
是 REQUIRED 组件。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 =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.registeredClientRepository(registeredClientRepository)
)
...
return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer |
OAuth2授权
An 是 OAuth2 授权的表示形式,它包含与资源所有者授予客户端的授权相关的状态,或者在授权授权类型的情况下,它自己也由其自身授予。OAuth2Authorization
client_credentials
Spring Security 的 OAuth2 客户端支持中相应的授权模型是 OAuth2AuthorizedClient。 |
成功完成授权授权流程后,将创建一个并关联 OAuth2AccessToken
、(可选)OAuth2RefreshToken
和特定于已执行授权授权类型的其他状态。OAuth2Authorization
与 关联的 OAuth2Token
实例会有所不同,具体取决于授权授权类型。OAuth2Authorization
对于 OAuth2 authorization_code 授权,将关联 an 、 an 和 an (可选)。OAuth2AuthorizationCode
OAuth2AccessToken
OAuth2RefreshToken
对于 OpenID Connect 1.0 authorization_code授权,将关联 、 OidcIdToken
、 和 (可选)。OAuth2AuthorizationCode
OAuth2AccessToken
OAuth2RefreshToken
对于 OAuth2 client_credentials 授权,仅关联 an。OAuth2AccessToken
OAuth2Authorization
其属性定义如下:
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 :特定于已执行授权授权类型的其他属性 – 例如,经过身份验证的 、 和其他。Principal OAuth2AuthorizationRequest |
OAuth2Authorization
及其关联的实例具有固定的生命周期。
新颁发的证书处于活动状态,并在过期或失效(撤销)时变为非活动状态。
当所有关联的实例都处于非活动状态时,它 is (隐式) inactive 。
每个 都包含在 中,该 为 、 和 提供访问器。OAuth2Token
OAuth2Token
OAuth2Authorization
OAuth2Token
OAuth2Token
OAuth2Authorization.Token
isExpired()
isInvalidated()
isActive()
OAuth2Authorization.Token
还提供 ,它返回与 关联的声明(如果有)。getClaims()
OAuth2Token
OAuth2AuthorizationService
它是存储新授权和查询现有授权的中心组件。
当遵循特定协议流时,其他组件会使用它,例如,客户端身份验证、授权授予处理、令牌自省、令牌吊销、动态客户端注册等。OAuth2AuthorizationService
提供的 are 和 .
该实现将实例存储在内存中,建议仅在开发和测试期间使用。 是一种 JDBC 实现,它使用 来持久化实例。OAuth2AuthorizationService
InMemoryOAuth2AuthorizationService
JdbcOAuth2AuthorizationService
InMemoryOAuth2AuthorizationService
OAuth2Authorization
JdbcOAuth2AuthorizationService
OAuth2Authorization
JdbcOperations
它是一个 OPTIONAL 组件,默认为 .OAuth2AuthorizationService InMemoryOAuth2AuthorizationService |
以下示例显示如何注册 :OAuth2AuthorizationService
@Bean
@Bean
public OAuth2AuthorizationService authorizationService() {
return new InMemoryOAuth2AuthorizationService();
}
或者,您可以通过 OAuth2AuthorizationServerConfigurer
进行配置:OAuth2AuthorizationService
@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 |
OAuth2授权同意
An 是来自 OAuth2 授权请求流的授权 “同意” (决定) 的表示形式,例如,授权,它包含资源所有者授予客户端的权限。OAuth2AuthorizationConsent
authorization_code
在授权客户端访问时,资源所有者只能授予客户端请求的权限子集。
典型的使用案例是授权流,其中客户端请求范围,资源所有者授予(或拒绝)对所请求范围的访问权限。authorization_code
OAuth2 授权请求流完成后,将创建(或更新)一个,并将授予的权限与客户端和资源所有者相关联。OAuth2AuthorizationConsent
OAuth2AuthorizationConsent
其属性定义如下:
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 授权请求流的组件使用,例如授权。OAuth2AuthorizationConsentService
authorization_code
提供的 are 和 .
该实现将实例存储在内存中,建议仅用于开发和测试。 是一种 JDBC 实现,它使用 来持久化实例。OAuth2AuthorizationConsentService
InMemoryOAuth2AuthorizationConsentService
JdbcOAuth2AuthorizationConsentService
InMemoryOAuth2AuthorizationConsentService
OAuth2AuthorizationConsent
JdbcOAuth2AuthorizationConsentService
OAuth2AuthorizationConsent
JdbcOperations
它是一个 OPTIONAL 组件,默认为 .OAuth2AuthorizationConsentService InMemoryOAuth2AuthorizationConsentService |
以下示例显示如何注册 :OAuth2AuthorizationConsentService
@Bean
@Bean
public OAuth2AuthorizationConsentService authorizationConsentService() {
return new InMemoryOAuth2AuthorizationConsentService();
}
或者,您可以通过 OAuth2AuthorizationServerConfigurer
进行配置:OAuth2AuthorizationConsentService
@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 关联的信息,并由 OAuth2TokenGenerator 和 OAuth2TokenCustomizer 使用。OAuth2TokenContext
OAuth2Token
OAuth2TokenContext
提供以下访问器:
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() :要生成的。支持的值为 、 、 和 。OAuth2TokenType code access_token refresh_token id_token |
7 | getAuthorizationGrantType() :与授权授权关联的。AuthorizationGrantType |
8 | getAuthorizationGrant() :处理授权的 使用的实例。Authentication AuthenticationProvider |
OAuth2令牌生成器
An 负责从提供的 OAuth2TokenContext 中包含的信息生成一个。OAuth2TokenGenerator
OAuth2Token
生成的 主要取决于 中指定的类型 。OAuth2Token
OAuth2TokenType
OAuth2TokenContext
例如,当 for 为:value
OAuth2TokenType
-
code
,然后生成。OAuth2AuthorizationCode
-
access_token
,然后生成。OAuth2AccessToken
-
refresh_token
,然后生成。OAuth2RefreshToken
-
id_token
,然后生成。OidcIdToken
此外,生成的格式会有所不同,具体取决于 RegisteredClient 的配置。
如果格式为 (默认),则生成 a。
如果格式为 ,则生成“不透明”令牌。OAuth2AccessToken
TokenSettings.getAccessTokenFormat()
OAuth2TokenFormat.SELF_CONTAINED
Jwt
OAuth2TokenFormat.REFERENCE
最后,如果生成的具有一组 claims 和 implements ,则可以从 OAuth2Authorization.Token.getClaims() 访问这些声明。OAuth2Token
ClaimAccessor
这主要由实施授权授权处理的组件使用,例如 、 和 。OAuth2TokenGenerator
authorization_code
client_credentials
refresh_token
提供的实现是 、 和 。
生成一个 “opaque” () 访问令牌,生成一个 ()。OAuth2AccessTokenGenerator
OAuth2RefreshTokenGenerator
JwtGenerator
OAuth2AccessTokenGenerator
OAuth2TokenFormat.REFERENCE
JwtGenerator
Jwt
OAuth2TokenFormat.SELF_CONTAINED
它是一个 OPTIONAL 组件,默认为 由 和 组成的 。OAuth2TokenGenerator DelegatingOAuth2TokenGenerator OAuth2AccessTokenGenerator OAuth2RefreshTokenGenerator |
如果已注册 a,则 a 将另外组成在 .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 =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.tokenGenerator(tokenGenerator)
)
...
return http.build();
}
在同时应用多个配置选项时,这很有用。OAuth2AuthorizationServerConfigurer |
OAuth2TokenCustomizer (OAuth2令牌自定义器)
An 提供了自定义 的属性的功能,这些属性可在提供的 OAuth2TokenContext 中访问。
OAuth2TokenGenerator 使用它来让它在生成之前自定义 的属性。OAuth2TokenCustomizer
OAuth2Token
OAuth2Token
使用泛型类型 () 声明的功能提供了自定义 “opaque” 的声明的能力。 提供对 的访问,从而允许添加、替换和删除声明。OAuth2TokenCustomizer<OAuth2TokenClaimsContext>
OAuth2TokenClaimsContext
implements OAuth2TokenContext
OAuth2AccessToken
OAuth2TokenClaimsContext.getClaims()
OAuth2TokenClaimsSet.Builder
以下示例显示了如何实现 an 并使用 an 配置它: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
};
}
如果未作为 提供或未通过 进行配置,则 将自动配置一个 。OAuth2TokenGenerator @Bean OAuth2AuthorizationServerConfigurer OAuth2TokenCustomizer<OAuth2TokenClaimsContext> @Bean OAuth2AccessTokenGenerator |
使用泛型类型 () 声明的 API 提供了自定义 . 提供对 的访问,从而允许添加、替换和删除标头。 提供对 的访问,从而允许添加、替换和删除声明。OAuth2TokenCustomizer<JwtEncodingContext>
JwtEncodingContext
implements OAuth2TokenContext
Jwt
JwtEncodingContext.getJwsHeader()
JwsHeader.Builder
JwtEncodingContext.getClaims()
JwtClaimsSet.Builder
以下示例显示如何实现 an 并使用 :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.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 OAuth2AuthorizationServerConfigurer OAuth2TokenCustomizer<JwtEncodingContext> @Bean JwtGenerator |
有关演示如何自定义 ID 令牌的示例,请参阅指南操作方法:自定义 OpenID Connect 1.0 UserInfo 响应。 |
SessionRegistry (会话注册表)
如果启用了 OpenID Connect 1.0,则实例将用于跟踪经过身份验证的会话。
它由 关联的 的默认实现 用于注册新的经过身份验证的会话。SessionRegistry
SessionRegistry
SessionAuthenticationStrategy
如果未注册 a,则将使用默认实现。SessionRegistry @Bean SessionRegistryImpl |
如果 已注册 并且是 的实例,则还应注册 ,因为它负责通知会话生命周期事件,例如,以提供删除实例的功能。SessionRegistry @Bean SessionRegistryImpl HttpSessionEventPublisher @Bean SessionRegistryImpl SessionDestroyedEvent SessionInformation |
当最终用户请求注销时,OpenID Connect 1.0 注销端点使用 查找与经过身份验证的最终用户关联的数据以执行注销。SessionRegistry
SessionInformation
如果正在使用 Spring Security 的并发会话控制功能,建议注册一个以确保它在 Spring Security 的并发会话控制和 Spring 授权服务器的注销功能之间共享。SessionRegistry
@Bean
以下示例显示如何注册 和 (需要):SessionRegistry
@Bean
HttpSessionEventPublisher
@Bean
SessionRegistryImpl
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}