SpringSecurityOAuth已停更,来看一看进化版本Spring Authorization Server

874 阅读6分钟

Spring Authorization Server是Spring Security OAuth的进化版本,Spring Security OAuth官方已经宣布“End of Life”了。Spring Security OAuth使用的是OAuth2.0标准而Spring Authorization Serve引入了对OAuth 2.1和OpenID Connect 1.0规范的支持,并提供了更多功能和改进。它提供了OAuth 2.1和OpenID Connect 1.0规范以及其他相关规范的实现。它是基于Spring Security构建的,为构建OpenID Connect 1.0身份提供者和OAuth2授权服务器产品提供了安全、轻量级和可定制的基础。

OAuth 2.1和OpenID Connect 1.0是用于身份验证和授权的行业标准协议。它们被广泛应用于各种应用程序和系统,以实现安全的用户身份验证和授权流程。Spring Authorization Server提供了一个方便的方式来实现这些协议,使开发人员能够快速构建安全可靠的身份验证和授权系统。

在本教程中,我们将介绍如何使用 Spring Boot 快速入门 Spring Authorization Server。

系统要求

在开始之前,您需要确保满足以下系统要求:

  • Java 17 或更高版本的运行时环境。

安装 Spring Authorization Server

首先,我们需要创建一个基于 Spring Boot 的项目,并添加 Spring Authorization Server 的依赖。

  1. 打开 start.spring.io,选择所需的项目配置,例如项目语言、构建工具和依赖管理器。
  2. 在依赖搜索框中输入 "spring-boot-starter-oauth2-authorization-server",并添加该依赖。
  • Maven

    org.springframework.boot spring-boot-starter-oauth2-authorization-server
  • Gradle

    implementation "org.springframework.security:spring-security-oauth2-authorization-server"

官方的版本可以选择1.1.0

  1. 下载生成的项目代码,并导入到您的开发环境中。

配置 Spring Authorization Server

一旦您的项目设置完毕,接下来需要进行一些配置以启用 Spring Authorization Server。

  1. 打开项目的 application.yml 文件。

  2. 添加以下配置内容:

    server: port: 9000

    logging: level: org.springframework.security: trace

    spring: security: oauth2: authorizationserver: client: oidc-client: registration: client-id: "oidc-client" client-secret: "{noop}secret" client-authentication-methods: - "client_secret_basic" authorization-grant-types: - "authorization_code" - "refresh_token" - "client_credentials" redirect-uris: - "http://127.0.0.1:8080/login/oauth2/code/oidc-client" post-logout-redirect-uris: - "http://127.0.0.1:8080/" scopes: - "openid" - "profile" require-authorization-consent: true

以上配置包含了一些必要的属性,例如服务器端口、客户端配置和授权相关设置。您可以根据自己的需求进行自定义配置。

开发您的第一个应用程序

现在,您可以开始编写您的第一个 Spring Authorization Server 应用程序了。

  1. 创建一个新的 Java 类,例如 AuthorizationServerConfig。

  2. 在类上添加 @Configuration 和 @EnableWebSecurity 注解。

  3. 定义以下必要的组件作为 @Bean:

    @Configuration @EnableWebSecurity public class SecurityConfig {

    /**
     * 配置授权服务相关端点
     * 负责处理与授权服务器相关的安全配置
     *  
    */
    @Bean 
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
    		throws Exception {
    	OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
    	http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
    		.oidc(Customizer.withDefaults());	// 启用 OpenID Connect 1.0
    	http
    		// 当未经过身份验证时,重定向到登录页面
    		.exceptionHandling((exceptions) -> exceptions
    			.defaultAuthenticationEntryPointFor(
    				new LoginUrlAuthenticationEntryPoint("/login"),
    				new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
    			)
    		)
    		// 接受访问令牌用于用户信息和/或客户端注册
    		.oauth2ResourceServer((resourceServer) -> resourceServer
    			.jwt(Customizer.withDefaults()));
    
    	return http.build();
    }
    
    

    /** * 配置资源相关端点 * 通用的过滤器链,用于处理整个应用程序的安全配置 */ @Bean @Order(2) public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .anyRequest().authenticated() ) // 表单登录处理授权服务器过滤器链的重定向 .formLogin(Customizer.withDefaults());

    	return http.build();
    }
    
    @Bean 
    public UserDetailsService userDetailsService() {
    	UserDetails userDetails = User.withDefaultPasswordEncoder()
    			.username("user")
    			.password("password")
    			.roles("USER")
    			.build();
    
    	return new InMemoryUserDetailsManager(userDetails);
    }
    
    @Bean 
    public RegisteredClientRepository registeredClientRepository() {
    	RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
    			.clientId("oidc-client")
    			.clientSecret("{noop}secret")
    			.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
    			.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
    			.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
    			.redirectUri("http://127.0.0.1:8080/login/oauth2/code/oidc-client")
    			.postLogoutRedirectUri("http://127.0.0.1:8080/")
    			.scope(OidcScopes.OPENID)
    			.scope(OidcScopes.PROFILE)
    			.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
    			.build();
    
    	return new InMemoryRegisteredClientRepository(oidcClient);
    }
    
    //JWK是一种JSON格式的密钥表示,用于描述加密算法使用的密钥。
    //JWT使用JWK进行签名和验证,确保令牌的真实性和完整性。
    @Bean 
    public JWKSource<SecurityContext> jwkSource() {
    	KeyPair keyPair = generateRsaKey();
    	RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    	RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    	RSAKey rsaKey = new RSAKey.Builder(publicKey)
    			.privateKey(privateKey)
    			.keyID(UUID.randomUUID().toString())
    			.build();
    	JWKSet jwkSet = new JWKSet(rsaKey);
    	return new ImmutableJWKSet<>(jwkSet);
    }
    
    private static KeyPair generateRsaKey() { 
    	KeyPair keyPair;
    	try {
    		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    		keyPairGenerator.initialize(2048);
    		keyPair = keyPairGenerator.generateKeyPair();
    	}
    	catch (Exception ex) {
    		throw new IllegalStateException(ex);
    	}
    	return keyPair;
    }
    
    @Bean 
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
    	return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }
    
    @Bean 
    public AuthorizationServerSettings authorizationServerSettings() {
    	return AuthorizationServerSettings.builder().build();
    }
    

    }

以上代码配置了 Spring Authorization Server 的一些必要组件,包括 HTTP 安全配置、密码编码器、认证管理器、JWT 访问令牌转换器、令牌存储和默认令牌服务。

  1. authorizationServerSecurityFilterChain用于协议端点的Spring Security过滤器链。 这个过滤器链用于处理与协议端点相关的请求和响应。它负责处理OAuth2和OpenID Connect的协议细节,例如授权请求、令牌颁发和验证等。
  2. defaultSecurityFilterChain用于身份验证的Spring Security过滤器链。 这个过滤器链用于处理身份验证相关的请求和响应。它负责验证用户的身份,并生成相应的凭据,以便后续的授权和访问控制。
  3. UserDetailsService的实例,用于获取需要进行身份验证的用户信息。 这个实例用于从用户存储中检索用户的详细信息,例如用户名、密码和权限等。它提供了与用户相关的数据,以便进行身份验证和授权的决策。
  4. RegisteredClientRepository的实例,用于管理客户端信息。 这个实例用于管理OAuth2和OpenID Connect客户端的注册信息,包括客户端ID、密钥、授权类型和重定向URI等。它负责验证客户端的身份并维护客户端的配置。
  5. com.nimbusds.jose.jwk.source.JWKSource的实例,用于对访问令牌进行签名。 这个实例用于生成和管理用于对访问令牌进行签名的JSON Web Key(JWK)。它提供了加密算法和密钥,以确保访问令牌的完整性和安全性。
  6. java.security.KeyPair的实例,用于在启动时生成密钥,并用于创建上述JWKSource。 这个实例用于生成公钥和私钥对,作为访问令牌签名所需的密钥材料。它提供了安全的密钥生成机制,以确保访问令牌的安全性和保密性。
  7. JwtDecoder的实例,用于解码已签名的访问令牌。 这个实例用于验证和解码已签名的访问令牌,以获取其中包含的授权信息和用户身份。它负责验证访问令牌的有效性和真实性。
  8. AuthorizationServerSettings的实例,用于配置Spring Authorization Server的设置。 这个实例用于配置Spring Authorization Server的一些全局设置,例如访问令牌的有效期、刷新令牌的策略和认证页面的URL等。它提供了对授权服务器行为的细粒度控制。

运行应用程序

现在,您已经完成了 Spring Authorization Server 的基本配置。您可以通过运行您的应用程序来启动服务器:

  1. 在项目中找到 Application 类,其中包含 main 方法。
  2. 运行 Application.main() 方法。

运行应用程序后,可以使用 OAuth 2.1 客户端来请求访问令牌,并使用访问令牌来访问受保护的资源。如:

以上是一个简单的 Spring Boot OAuth 2.0 的 demo 示例,仅供参考。在实际开发中,需要根据具体业务需求和安全要求进行相应的配置和实现。

相关demo源代码

  • Spring Authorization Server官方demo(基于springboot)

github.com/spring-proj…

  • Spring Security官方demo(基于springboot)

github.com/spring-proj…

运行效果

登录页面

  • 登录后主页面

通过授权码模式获取resource

通过Device Activation模式获取resource

====================================

如果文章对你有帮忙,请不要忘记加个关注、点个赞!必回关!!!