如果您的项目已经引入spring-security-oauth2
,则可以利用一些自动配置来简化设置授权和资源服务器。有关完整的详细信息,请参阅《 Spring Security OAuth 2开发人员指南》。
以下项目处于维护阶段:
- spring-security-oauth2
- spring-security-oauth2-autoconfigure
当然,欢迎您使用它们,我们将为您提供帮助!
但是,在选择
spring-security-oauth2
和spring-security-oauth2-autoconfigure
之前,您应该查看Spring Security功能列表,以查看新的 first-class support是否满足您的需求。该项目是Spring Boot 1.x附带的Spring Security OAuth支持的端口。在Spring Boot 2.x中删除了支持,以支持Spring Security 5’s first-class OAuth support。
为了简化迁移,该项目作为旧版Spring Security OAuth支持与Spring Boot 2.x之间的桥梁而存在。
1.授权服务器
Spring Security OAuth2引导简化了OAuth 2.0授权服务器的安装。
1.1 我需要开启自己的授权服务吗?
在以下情况下,您需要开启自己的授权服务:
- 您希望将登录,注销和密码重置的操作委派给您要管理的独立服务(也称为identity federation)。
- 您想使用OAuth 2.0协议将此单独的服务与其他服务配合使用
1.2 依赖
要使用此库中的自动配置功能,您需要spring-security-oauth2
,它具有原生OAuth 2.0和spring-security-oauth2-autoconfigure
。请注意,您需要为spring-security-oauth2-autoconfigure
指定版本,因为它不再由Spring Boot管理,尽管它仍然应该与Boot的版本匹配。
对于JWT支持,您还需要spring-security-jwt
。
1.3 OAuth2最小配置引导
创建最小的Spring Boot授权服务器包括三个基本步骤:
- 引入依赖
- 加上@EnableAuthorizationServer注解
- 指定至少一个客户端client ID和client-secret。
1.3.1 启动授权服务器
与其他Spring Boot @Enable注解类似,您可以将@EnableAuthorizationServer注解添加到包含main方法的类中,如以下示例所示:
@EnableAuthorizationServer
@SpringBootApplication
public class SimpleAuthorizationServerApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleAuthorizationServerApplication, args);
}
}
添加此注解会导入其他Spring配置文件,这些文件会添加许多合理的默认项,例如应该如何对令牌进行签名,令牌的持续时间以及允许的授权范围。
1.3.2 指定一个Client和Secret
根据规范,许多OAuth 2.0端点都需要客户端身份验证,因此您需要至少指定一个客户端,以便任何人都可以与您的授权服务器进行通信。
security:
oauth2:
client:
client-id: first-client
client-secret: noonewilleverguess
尽管很方便,但是这导致了许多在生产中不太可行的情况。您可能需要做的比这更多。
您如何处理它?接下来我们将介绍。
1.3.3 检索令牌
OAuth 2.0本质上是一个框架,用于指定将long-lived令牌交换为short-lived令牌的策略。
默认情况下,@EnableAuthorizationServer
授予客户端访问客户端凭据的权限,这意味着您可以执行以下操作:
curl first-client:noonewilleverguess@localhost:8080/oauth/token -dgrant_type=client_credentials -dscope=any
获取到的内容如下:
{
"access_token" : "f05a1ea7-4c80-4583-a123-dc7a99415588",
"token_type" : "bearer",
"expires_in" : 43173,
"scope" : "any"
}
可以将该令牌提供给支持不透明OAuth 2.0令牌的任何资源服务器,并将其授权指向配置为此授权服务器进行验证。
从这里,您可以跳至:
- 如何关闭OAuth2引导程序的自动配置
- 如何使授权码授予流程起作用
- 如何使密码授予流程起作用
- 如何以及何时为授权服务器提供AuthenticationManager
- 授权服务器与Spring Security 5.1资源服务器和客户端兼容吗?
- 如何配置Jwt令牌
1.4 如何关闭OAuth2引导程序的自动配置
一般地,OAuth2 Boot项目会创建一个AuthorizationServerConfigurer
实例,并带有一些合理的默认值:
- 它注册一个
NoOpPasswordEncoder
(覆盖Spring Security的默认项) - 它使您提供的客户端可以使用该服务器支持的任何授权类型:
authorization_code
,password
,client_credentials
,隐式
或refresh_token
。
另外,它也会尝试装配一些bean(如果已定义)-即:
-
AuthenticationManager
:用于查找最终用户(不是客户端) -
TokenStore
:用于生成和检索令牌 -
AccessTokenConverter
:用于将访问令牌转换为不同的格式,例如JWT。
尽管本文档介绍了每种Bean的功能,但Spring Security OAuth文档是阅读其原始功能的更好位置
如果您配置了一个AuthorizationServerConfigurer
类型的bean,则不会自动完成任何操作.
例如,如果您需要配置多个客户端,更改其允许的授予类型或使用比NoOpPasswordEncoder
更好的方式(强烈建议!),如果您想要配置自己的AuthorizationServerConfigurer
,参考如下示例:
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired DataSource dataSource;
protected void configure(ClientDetailsServiceConfigurer clients) {
clients
.jdbc(this.dataSource)
.passwordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
}
}
前面的配置使OAuth2 Boot不再从环境属性中检索客户端,现在回退到Spring Security密码授权的默认方式。
了解更多相关文档:
1.5 如何使授权码授权模式起作用
使用默认配置,虽然从技术上允许使用授权码模式,但尚未完全配置它。这是因为,除了预先配置的内容外,授权代码流还需要:
- 终端用户
- 终端用户登录流程
- 向客户端注册的重定向URI
1.5.1 添加终端用户
在使用Spring Security的传统Spring Boot应用程序中,用户由UserDetailsService
定义。在这方面,授权服务器没有什么不同,如以下示例所示:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder()
.username("enduser")
.password("password")
.roles("USER")
.build());
}
}
请注意,就像传统的Spring Security Web应用程序一样,用户是在WebSecurityConfigurerAdapter实例中定义的。
1.5.2 添加最终用户登录流程
顺便说一句,现在添加WebSecurityConfigurerAdapter
实例就是为最终用户添加表单登录流程所需要的。然而,请注意,这是Web程序本身配置(而不是OAuth 2.0 API的)。
如果您要自定义登录页面,为用户提供的不仅仅是表单登录,还要添加其他支持(如密码重置),WebSecurityConfigurerAdapter
会选择它
1.5.3 向客户端注册的重定向URI
OAuth2 Boot不支持将重定向URI配置为属性(例如,与client-id和client-secret一起使用)。
要添加重定向URI,您需要使用InMemoryClientDetailsService
或JdbcClientDetailsService
指定客户端。
进行以下任一操作都意味着用您自己的OAuth2 Boot提供的AuthorizationServerConfigurer
替换,如以下示例所示:
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
protected void configure(ClientDetailsServiceConfigurer clients) {
clients
.inMemory()
.withClient("first-client")
.secret(passwordEncoder().encode("noonewilleverguess"))
.scopes("resource:read")
.authorizedGrantTypes("authorization_code")
.redirectUris("http://localhost:8081/oauth/login/client-app");
}
}
1.5.4. 测试授权码流程
测试OAuth可能很棘手,因为它需要多个服务器来查看完整的操作流程。但是,第一步很简单:
- 访问
http://localhost:8080/oauth/authorize?grant_type=authorization_code&response_type = code&client_id=first-client&state=1234
- 如果用户未登录,则该应用程序将重定向到登录页面,
http://localhost:8080/login
- 用户登录后,应用程序将生成code并重定向到已注册的重定向URI。在本例中,该地址为
http:// localhost:8081/oauth/login/client-app
此时,可以通过启动配置为不透明令牌配置并指向此授权服务器实例的任何资源服务器来继续该流程。
1.6. 如何使密码授权模式起作用
使用默认配置,虽然从技术上讲可能存在密码授权模式,但它与授权码一样,都缺少用户。
就是说,由于默认配置会创建一个具有用户名user和随机生成的密码的用户,因此,可以检查带有该密码的日志并执行以下操作:
curl first-client:noonewilleverguess@localhost:8080/oauth/token -dgrant_type=password -dscope=any -dusername=user -dpassword=the-password-from-the-logs
当您运行该命令时,您应会该获得一个令牌。
但是,您更有可能要指定一组用户。
如1.5 如何使授权码授权流程起作用中所述,在Spring Security
中,通常在UserDetailsService
中指定用户,并且此应用也一样,如以下示例所示:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder()
.username("enduser")
.password("password")
.roles("USER")
.build());
}
}
这就是我们需要做的。我们不需要重写AuthorizationServerConfigurer
,因为客户端ID和密码被指定为环境属性。
因此,以下内容现在应该起作用:
curl first-client:noonewilleverguess@localhost:8080/oauth/token -dgrant_type=password -dscope=any -dusername=enduser -dpassword=password
1.7 如何以及何时为授权服务器提供AuthenticationManager
这是一个非常常见的问题,当AuthorizationServerEndpointsConfigurer
需要指定AuthenticationManager
实例时,不是很直观。简短的答案是:仅在使用资源所有者密码模式时。
记住一些基本知识会有所帮助:
-
AuthenticationManager
是用于认证用户的抽象。它通常需要指定某种UserDetailsService
才能完成。 - 最终用户在
WebSecurityConfigurerAdapter
中指定。 - 默认情况下,OAuth2 Boot程序会自动选择任何公开的
AuthenticationManager
。
但是,并非所有模式都需要AuthenticationManager
,因为并非所有模式都涉及最终用户。例如,“客户凭证”模式仅基于客户的权限而不是最终用户的权限来请求令牌。并且“刷新令牌”模式仅基于刷新令牌的权限来请求令牌。
另外,并非所有模式都明确要求OAuth 2.0 API本身也具有AuthenticationManager
。例如,授权码和隐式模式在用户登录(应用程序流程)时而不是在请求令牌(OAuth 2.0 API)时验证用户。
仅资源所有者密码模式返回基于最终用户凭据的code。这意味着,当客户端使用资源所有者密码模式时,授权服务器仅需要AuthenticationManager
。
以下示例展示了“资源所有者密码”模式:
.authorizedGrantTypes("password", ...)
在以上流程中,您的授权服务器需要AuthenticationManager
的实例。
有几种方法可以做到这一点(记住前面的基本原理):
- 保留OAuth2引导默认值(您不配置
AuthorizationServerConfigurer
)并配置UserDetailsService
。 - 保留OAuth2 Boot的默认设置,并配置
AuthenticationManager
。 - 重写
AuthorizationServerConfigurerAdapter
(删除OAuth2 Boot程序的默认配置),并依赖AuthenticationConfiguration
。 - 重写
AuthorizationServerConfigurerAdapter
并手动连接AuthenticationManager
。
1.7.1 配置UserDetailsService
终端用户是通过UserDetailsService
在WebSecurityConfigurerAdapter
中指定的。因此,如果您使用OAuth2 Boot程序的默认设置(即您尚未实现AuthorizationServerConfigurer
),则可以配置UserDetailsService
并完成操作,如以下示例所示:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired DataSource dataSource;
@Bean
@Override
public UserDetailsService userDetailsService() {
return new JdbcUserDetailsManager(this.dataSource);
}
}
1.7.2 配置AuthenticationManager
如果需要对AuthenticationManager
进行更专门的配置,可以在WebSecurityConfigurerAdapter
中进行配置,然后将其公开,如以下示例所示:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean(BeansId.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customAuthenticationProvider());
}
}
如果您使用默认的OAuth2 Boot配置,它将自动装配Bean。
1.7.3 依赖AuthenticationConfiguration
在AuthenticationConfiguration
中可以使用任何已配置的AuthenticationManager
。这意味着,如果需要一个AuthorizationServerConfigurer
(在这种情况下,您需要自己进行自动装配),则可以依赖AuthenticationConfiguration
来获取AuthenticationManager
bean,如以下类所示:
@Component
public class CustomAuthorizationServerConfigurer extends
AuthorizationServerConfigurerAdapter {
AuthenticationManager authenticationManager;
public CustomAuthorizationServerConfigurer(AuthenticationConfiguration authenticationConfiguration) {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) {
// .. your client configuration that allows the password grant
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager);
}
}
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
return new MyCustomUserDetailsService();
}
}
1.7.4 手动连接AuthenticationManager
在最复杂的情况下,AuthenticationManager
需要特殊配置,并且您拥有自己的AuthenticationServerConfigurer
,那么您既需要创建自己的AuthorizationServerConfigurerAdapter
,也需要创建自己的WebSecurityConfigurerAdapter
:
@Component
public class CustomAuthorizationServerConfigurer extends
AuthorizationServerConfigurerAdapter {
AuthenticationManager authenticationManager;
public CustomAuthorizationServerConfigurer(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) {
// .. your client configuration that allows the password grant
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager);
}
}
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean(BeansId.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customAuthenticationProvider());
}
}
1.8 授权服务器与Spring Security 5.1资源服务器和客户端兼容吗?
不,不是开箱即用的。 Spring Security 5.1仅支持JWT编码的JWK签名授权,并且Authorization Server不附带JWK Set URI。
不过,可以提供基本支持。
例如,为了将Authorization Server配置为与Spring Security 5.1 Resource Server兼容,您需要执行以下操作:
- 配置它以使用JWK
- 添加JWK设置URI端点
1.8.1 配置授权服务器以使用JWK
要更改用于访问和刷新令牌的格式,可以更改AccessTokenConverter
和TokenStore
,如以下示例所示:
@EnableAuthorizationServer
@Configuration
public class JwkSetConfiguration extends AuthorizationServerConfigurerAdapter {
AuthenticationManager authenticationManager;
KeyPair keyPair;
public JwkSetConfiguration(AuthenticationConfiguration authenticationConfiguration,
KeyPair keyPair) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
this.keyPair = keyPair;
}
// ... client configuration, etc.
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
// @formatter:off
endpoints
.authenticationManager(this.authenticationManager)
.accessTokenConverter(accessTokenConverter())
.tokenStore(tokenStore());
// @formatter:on
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(this.keyPair);
return converter;
}
}
1.8.2 添加JWK设置URI端点
Spring Security OAuth不支持JWK,@EnableAuthorizationServer
也不支持向其初始集合添加更多OAuth 2.0 API端点。但是,我们仅可以添加几行。
首先,您需要添加另一个依赖项:com.nimbusds:nimbus-jose-jwt
。这为您提供了适当的JWK支持。
其次,您无需直接使用@EnableAuthorizationServer
,而是直接包含其两个@Configuration
类:
-
AuthorizationServerEndpointsConfiguratio
n:用于配置OAuth 2.0 API端点的@Configuration
类,例如用于令牌的格式。 -
AuthorizationServerSecurityConfiguration
:这些端点周围的访问规则的@Configuration
类。这是您需要扩展的扩展,如以下示例所示:
@FrameworkEndpoint
class JwkSetEndpoint {
KeyPair keyPair;
public JwkSetEndpoint(KeyPair keyPair) {
this.keyPair = keyPair;
}
@GetMapping("/.well-known/jwks.json")
@ResponseBody
public Map<String, Object> getKey(Principal principal) {
RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic();
RSAKey key = new RSAKey.Builder(publicKey).build();
return new JWKSet(key).toJSONObject();
}
}
@Configuration
class JwkSetEndpointConfiguration extends AuthorizationServerSecurityConfiguration {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.requestMatchers()
.mvcMatchers("/.well-known/jwks.json")
.and()
.authorizeRequests()
.mvcMatchers("/.well-known/jwks.json").permitAll();
}
}
然后,由于不需要更改AuthorizationServerEndpointsConfiguration
,因此可以@Import
而不是使用@EnableAuthorizationServer
,如以下示例所示:
@Import(AuthorizationServerEndpointsConfiguration.class)
@Configuration
public class JwkSetConfiguration extends AuthorizationServerConfigurerAdapter {
// ... the rest of the configuration from the previous section
}
1.8.3 针对Spring Security 5.1资源服务器进行测试
现在您可以POST到/oauth /token端点(如前所述)以获取令牌,然后将其提供给Spring Security 5.1资源服务器。
相关推荐
OAuth2 是一个授权框架,广泛应用于现代Web应用和API的安全性设计,允许第三方应用在用户许可的情况下访问受保护的资源。本套系统包含了授权服务器、资源服务器和客户端,旨在实现安全的单点登录(Single Sign-On, ...
OAuth2 授权框架与 Spring Boot 集成指南 OAuth2 授权框架是一种协议,允许用户授权第三方网站或应用程序访问用户受保护的资源,而不必披露其长期凭据甚至身份。OAuth 引入了一个授权层,将客户端角色与资源所有者...
Spring Boot Security OAuth2 是一个广泛使用的框架,用于构建安全、授权的API服务。本项目重点在于实现一个支持JWT(JSON Web Token)令牌的授权服务器,这将使我们能够为客户端提供安全的认证和授权。 首先,让...
SpringBoot整合OAuth2和Gateway实现网关登录授权验证是...通过理解OAuth2的授权机制、Spring Boot的安全配置以及Spring Gateway的过滤器功能,我们可以构建一个安全、高效的服务网关,为微服务架构提供强大的安全保障。
OAuth2则是一种授权框架,用于保护API资源的安全,允许第三方应用在用户授权下访问资源服务器的数据。本篇文章将深入探讨如何在Spring Boot 2项目中结合Security和OAuth2实现安全认证,并将令牌存储到数据库中。 ...
本篇文章将围绕“spring-boot spring-security-oauth2 完整demo”这一主题,详细阐述这三个框架如何协同工作,以及如何通过类似微信的方式获取token并访问资源。 首先,Spring Boot是基于Spring框架的快速开发工具...
1. **设置OAuth2授权服务器**:在Spring Boot项目中,我们需要创建一个授权服务器来处理用户的授权请求。这可以通过实现`AuthorizationServerConfigurerAdapter`并配置必要的端点如授权端点、令牌端点来完成。 2. *...
授权码模式是OAuth2的四种授权类型之一,适用于服务器端应用,因为它可以保护用户的密码不被第三方应用获取。 在Spring Boot环境中,我们可以利用Spring Security OAuth2模块来实现这个功能。以下是一些关键步骤: ...
OAuth2官方文档翻译。翻译自地址https://docs.spring.io/spring-security-oauth2-boot/docs/current/reference/htmlsingle/#boot-features-security-oauth2-single-sign-on。翻译完成日期为2020年3月19日。如需转载...
在Spring Security OAuth2中,创建一个授权服务器需要使用`@EnableAuthorizationServer`注解,并且扩展`AuthorizationServerConfigurerAdapter`类。以下是一个配置示例: ```java @Configuration @...
本教程将探讨如何使用Spring Boot结合Spring Security、OAuth2和JWT(JSON Web Token)来搭建一个认证服务器、API网关以及微服务之间的权限认证和授权机制。 首先,Spring Security是Spring框架的一个模块,专门...
OAuth2 是一个授权框架,常用于构建安全的API和实现单点登录(Single Sign-On, SSO)。在SSO场景中,用户只需登录一次就能访问多个应用,无需反复输入用户名和密码,极大地提升了用户体验。本资源包含了一份关于...
OAuth2.0的核心是授权流程,包括四个主要角色:资源所有者(用户)、客户端(第三方应用)、资源服务器(用户数据所在的服务器)和授权服务器(处理授权请求的服务器)。流程通常包括授权码获取、访问令牌获取和...
Spring Boot 2 Oauth2资源和授权服务器 使用用户和客户端数据库(JPA,Hibernate,MySQL)的Spring Boot 2 OAuth2资源和授权服务器实现 入门 这些说明将为您提供在本地计算机上运行并运行的项目的副本,以进行开发...
Spring Security OAuth2 Boot 2.6.8作为最后一版的官方文档,提供了关于如何使用Spring Security OAuth2 Boot来简化授权和资源服务器设置的方法。这一版本支持Spring Boot 2.x,并作为旧版Spring Security OAuth支持...
2. **授权码获取**:资源拥有者同意授权后,授权服务器会生成一个授权码,并将其发送给客户端。 3. **访问令牌获取**:客户端使用授权码向授权服务器申请访问令牌。 4. **访问令牌使用**:客户端使用获得的访问...
在Spring Boot和Spring Security的整合中,授权服务器通常由Spring Security OAuth2组件扮演,它负责处理授权请求,生成访问令牌;资源服务器则是Spring Boot应用,它接收并验证令牌,决定是否允许访问受保护的资源...
总的来说,这个项目提供了一个全面的OAuth2认证解决方案,包括服务端的授权服务器和资源服务器,以及客户端的OAuth2集成和第三方登录功能。开发者可以通过学习和修改这个项目,快速地在自己的Spring Boot应用中实现...
OAuth2 是一个授权框架,它允许第三方应用请求有限的访问权限,而不必让用户暴露他们的用户名和密码给第三方应用。OAuth2 协议定义了四种授权模式,分别为授权码模式、隐式授权模式、密码模式和客户端模式。 在授权...
OAuth2是一种广泛应用于互联网的开放授权协议,它允许第三方应用在用户许可的情况下,获取到一定的权限,以便与用户的资源进行交互。在这个“Oauth2_淘宝授权JAVA前后端源代码demo”项目中,我们将深入探讨如何在...