[关闭]
@levinzhang 2023-01-07T22:00:21.000000Z 字数 5446 阅读 556

Spring Authorization Server 1.0提供了OAuth 2.1和OpenID Connect 1.0实现

by

摘要:

在向Java社区推出两年半之后,VMWare发布了Spring Authorization Server 1.0。Spring Authorization Server项目构建在Spring Security之上,支持OpenID Connect 1.0 Identity Provider和OAuth 2.1 Authorization Server。该项目取代了业已不再维护的Spring Security OAuth项目。

在向Java社区推出两年半之后,VMWare发布了Spring Authorization Server 1.0。 Spring Authorization Server项目构建在Spring Security之上,支持创建OpenID Connect 1.0 Identity Provider和OAuth 2.1 Authorization Server。该项目取代了业已不再维护的Spring Security OAuth项目。

Spring Authorization Server也基于Spring Framework 6.0,需要使用Java 17作为最低版本。该项目支持特征列表中描述的Authorization Grants、Token Format、Client Authentication和Protocol Endpoints。

有个示例应用阐述了使用Spring Initializr创建Spring Boot应用的基本配置。该示例应用是基于REST的,需要在pom.xml文件中包含spring-boot-starter-web依赖:

  1. dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>

为了阐述登录功能,请考虑如下创建REST端点的样例:

  1. @RestController
  2. public class TimeController {
  3. @GetMapping("/time")
  4. public String retrieveTime() {
  5. DateTimeFormatter dateTimeFormatter =
  6. DateTimeFormatter.ofPattern("HH:mm:ss");
  7. LocalTime localTime = LocalTime.now();
  8. return dateTimeFormatter.format(localTime);
  9. }
  10. }

一个基础的Spring Boot应用类用来启动应用与前文创建的REST端点:

  1. @SpringBootApplication
  2. public class TimeApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(TimeApplication.class, args);
  5. }
  6. }

在启动应用之后,打开http://localhost:8080/time URL,将会显示当前时间:

  1. 21:00:34

现在,我们添加Spring Authorization Server依赖:

  1. <dependency>
  2. <groupId>org.springframework.security</groupId>
  3. <artifactId>spring-security-oauth2-authorization-server</artifactId>
  4. <version>1.0.0</version>
  5. </dependency>

当再次启动应用后,日志中会打印出密码,例如:

  1. Using generated security password: d73d5904-25a1-44ed-91e1-a32c4c5aedb8

现在,当访问http://localhost:8080/time时,请求会重定向到http://localhost:8080/login,并展示如下所示的页面:

我们使用默认的用户名user以及打印出的密码登录之后,请求会被重定向到http://localhost:8080/time?continue,并再次显示当前时间。

“开发第一个样例”文档详细介绍了Spring Authorization Server需要的几个@Bean组件,它们应该定义在带有@Configuration注解的类中。第一个bean用来定义OAuth2 Protocol Endpoint

  1. @Bean
  2. @Order(1)
  3. public SecurityFilterChain protocolFilterChain(HttpSecurity http)
  4. throws Exception {
  5. OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
  6. http
  7. .exceptionHandling((exceptions) -> exceptions
  8. .authenticationEntryPoint(
  9. new LoginUrlAuthenticationEntryPoint("/login"))
  10. )
  11. .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)
  12. .getConfigurer(OAuth2AuthorizationServerConfigurer.class)
  13. .oidc(Customizer.withDefaults());
  14. return http.build();
  15. }

第二个bean用来定义Spring Security Authentication

  1. @Bean
  2. @Order(2)
  3. public SecurityFilterChain authenticationFilterChain(HttpSecurity http) throws Exception {
  4. http
  5. .authorizeHttpRequests((authorize) -> authorize
  6. .anyRequest().authenticated()
  7. )
  8. .formLogin(Customizer.withDefaults());
  9. return http.build();
  10. }

在真正的产品中,我们应该使用合理的方案来存储用户,但是在这个简单的样例中,用户james和密码gosling存储在了内存中:

  1. @Bean
  2. public UserDetailsService userDetailsService() {
  3. UserDetails userDetails = User.withDefaultPasswordEncoder()
  4. .username("james")
  5. .password("gosling")
  6. .roles("FOUNDER")
  7. .build();
  8. return new InMemoryUserDetailsManager(userDetails);
  9. }

新的客户端使用RegisteredClientRepository注册在了内存中:

  1. @Bean
  2. public RegisteredClientRepository registeredClientRepository() {
  3. RegisteredClient registeredClient =
  4. RegisteredClient.withId(UUID.randomUUID().toString())
  5. .clientId("id")
  6. .clientSecret("secret")
  7. .clientAuthenticationMethod(
  8. ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
  9. .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
  10. .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
  11. .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
  12. .redirectUri(
  13. "http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
  14. .redirectUri("http://127.0.0.1:8080/authorized")
  15. .scope(OidcScopes.OPENID)
  16. .scope(OidcScopes.PROFILE)
  17. .scope("message.read")
  18. .scope("message.write")
  19. .clientSettings(
  20. ClientSettings.builder()
  21. .requireAuthorizationConsent(true).build())
  22. .build();
  23. return new InMemoryRegisteredClientRepository(registeredClient);
  24. }

访问令牌会使用如下的bean进行签名,它会使用com.nimbusds.jose.jwk.RSAKey,而不是java.security.interfaces.RSAKey

  1. @Bean
  2. public JWKSource<SecurityContext> jwkSource() {
  3. KeyPair keyPair = generateRsaKey();
  4. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  5. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  6. RSAKey rsaKey = new RSAKey.Builder(publicKey)
  7. .privateKey(privateKey)
  8. .keyID(UUID.randomUUID().toString())
  9. .build();
  10. JWKSet jwkSet = new JWKSet(rsaKey);
  11. return new ImmutableJWKSet<>(jwkSet);
  12. }
  13. private static KeyPair generateRsaKey() {
  14. KeyPair keyPair;
  15. try {
  16. KeyPairGenerator keyPairGenerator =
  17. KeyPairGenerator.getInstance("RSA");
  18. keyPairGenerator.initialize(2048);
  19. keyPair = keyPairGenerator.generateKeyPair();
  20. }
  21. catch (Exception ex) {
  22. throw new IllegalStateException(ex);
  23. }
  24. return keyPair;
  25. }

JwtDecoder会用来解码已签名的访问令牌,它会使用com.nimbusds.jose.proc.SecurityContext,而不是org.springframework.security.core.context.SecurityContext

  1. @Bean
  2. public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
  3. return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
  4. }

最后,AuthorizationServerSettings会用来配置OAuth2认证服务器:

  1. @Bean
  2. public AuthorizationServerSettings authorizationServerSettings() {
  3. return AuthorizationServerSettings.builder().build();
  4. }

现在,当浏览http://localhost:8080/time时,可以使用用户名james和密码gosling来查看当前的时间。在遵循这些步骤后,该应用可以扩展为使用各种OAuth2和OpenID Connect 1.0功能,如令牌。

有多个视频对Spring Authorization Server进行了详细解释,例如Spring Security团队的核心提交者Joe Grandja在旧金山JUG上做了Spring Authorization Server入门的演讲,Spring Security in Action的作者Laurentiu Spilca在Spring I/O上介绍了如何使用Spring Security实现OAuth 2认证服务器

该项目是基于VMware Tanzu开源软件支持策略发布的,这意味着主要版本的支持时间长达三年。另外,VMware还提供24/7的商业支持

更多信息可以参考入门指南参考文档和GitHub上的示例

查看英文原文:Spring Authorization Server 1.0 Provides Oauth 2.1 and OpenID Connect 1.0 Implementations

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注