Getting Started
如果你刚开始使用 Spring Authorization Server,则以下部分将指导你创建你的第一个应用程序。
If you are just getting started with Spring Authorization Server, the following sections walk you through creating your first application.
System Requirements
Spring Authorization Server 需要 Java 17 或更高版本的运行时环境。
Spring Authorization Server requires a Java 17 or higher Runtime Environment.
Installing Spring Authorization Server
Spring Authorization Server可以用在您已在其中使用 Spring Security的任何地方。
Spring Authorization Server can be used anywhere you already use Spring Security.
开始使用Spring Authorization Server的最简单方法是创建一个基于 Spring Boot的应用程序。您可以使用 start.spring.io生成基本项目或使用 default authorization server sample作为指导。然后将Spring Boot的starter for Spring Authorization Server添加为依赖项:
The easiest way to begin using Spring Authorization Server is by creating a Spring Boot-based application. You can use start.spring.io to generate a basic project or use the default authorization server sample as a guide. Then add Spring Boot’s starter for Spring Authorization Server as a dependency:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
implementation "org.springframework.boot:spring-boot-starter-oauth2-authorization-server"
请参阅 Installing Spring Boot以了解更多有关与 Maven 或 Gradle 一起使用 Spring Boot 的信息。 |
See Installing Spring Boot for more information on using Spring Boot with Maven or Gradle. |
或者,你可以使用以下示例在不使用 Spring Boot 的情况下添加 Spring Authorization Server:
Alternatively, you can add Spring Authorization Server without Spring Boot using the following example:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>{spring-authorization-server-version}</version>
</dependency>
implementation "org.springframework.security:spring-security-oauth2-authorization-server:{spring-authorization-server-version}"
Developing Your First Application
若要开始,你需要将所需组件定义为 @Bean
。在使用 spring-boot-starter-oauth2-authorization-server
依赖项时,定义以下属性,Spring Boot 将为你提供必要的 @Bean
定义:
To get started, you need the minimum required components defined as a @Bean
. When using the spring-boot-starter-oauth2-authorization-server
dependency, define the following properties and Spring Boot will provide the necessary @Bean
definitions for you:
server:
port: 9000
logging:
level:
org.springframework.security: trace
spring:
security:
user:
name: user
password: password
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"
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
除了入门体验之外,大多数用户都希望自定义默认配置。next section演示了如何自己提供所有必需 Bean。 |
Beyond the Getting Started experience, most users will want to customize the default configuration. The next section demonstrates providing all of the necessary beans yourself. |
Defining Required Components
如果你想自定义默认配置(无论是否使用 Spring Boot),可以在 Spring @Configuration
中将所需组件定义为一个 @Bean
。
If you want to customize the default configuration (regardless of whether you’re using Spring Boot), you can define the minimum required components as a @Bean
in a Spring @Configuration
.
可以按以下方式定义这些组件:
These components can be defined as follows:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean (1)
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
http
// Redirect to the login page when not authenticated from the
// authorization endpoint
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
)
// Accept access tokens for User Info and/or Client Registration
.oauth2ResourceServer((resourceServer) -> resourceServer
.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean (2)
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
// Form login handles the redirect to the login page from the
// authorization server filter chain
.formLogin(Customizer.withDefaults());
return http.build();
}
@Bean (3)
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
@Bean (4)
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);
}
@Bean (5)
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() { (6)
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
@Bean (7)
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
@Bean (8)
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build();
}
}
这是一个快速上手使用的最小配置。要了解每个组件的用途,请参阅以下说明:
This is a minimal configuration for getting started quickly. To understand what each component is used for, see the following descriptions:
1 | A Spring Security filter chain for the Protocol Endpoints. |
2 | A Spring Security filter chain for authentication. |
3 | An instance of UserDetailsService for retrieving users to authenticate. |
4 | An instance of RegisteredClientRepository for managing clients. |
5 | An instance of com.nimbusds.jose.jwk.source.JWKSource for signing access tokens. |
6 | An instance of java.security.KeyPair with keys generated on startup used to create the JWKSource above. |
7 | An instance of JwtDecoder for decoding signed access tokens. |
8 | An instance of AuthorizationServerSettings to configure Spring Authorization Server. |