開始使用
如果您剛開始使用 Spring Authorization Server,以下章節將引導您建立您的第一個應用程式。
安裝 Spring Authorization Server
Spring Authorization Server 可以用於任何您已使用 Spring Security 的地方。
開始使用 Spring Authorization Server 最簡單的方式是建立一個基於 Spring Boot 的應用程式。您可以使用 start.spring.io 產生一個基本專案,或使用 預設授權伺服器範例 作為指南。然後新增 Spring Boot 的 Spring Authorization Server 啟動器作為依賴項
-
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"
請參閱 安裝 Spring Boot 以取得更多關於搭配 Maven 或 Gradle 使用 Spring Boot 的資訊。 |
或者,您可以使用以下範例在沒有 Spring Boot 的情況下新增 Spring Authorization Server
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>1.3.3</version>
</dependency>
implementation "org.springframework.security:spring-security-oauth2-authorization-server:1.3.3"
開發您的第一個應用程式
若要開始使用,您需要定義為 @Bean
的最低需求組件。當使用 spring-boot-starter-oauth2-authorization-server
依賴項時,定義以下屬性,Spring Boot 將為您提供必要的 @Bean
定義。
application.yml
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
除了開始使用體驗之外,大多數使用者會想要自訂預設組態。 下一節 示範如何自行提供所有必要的 bean。 |
定義需求組件
如果您想要自訂預設組態 (無論您是否使用 Spring Boot),您可以在 Spring @Configuration
中將最低需求組件定義為 @Bean
。
這些組件可以定義如下:
SecurityConfig.java
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();
}
}
這是一個用於快速入門的最小組態。若要了解每個組件的用途,請參閱以下說明:
1 | 用於 協定端點 的 Spring Security 篩選器鏈。 |
2 | 用於 身份驗證 的 Spring Security 篩選器鏈。 |
3 | 用於檢索使用者以進行身份驗證的 UserDetailsService 實例。 |
4 | 用於管理客戶端的 RegisteredClientRepository 實例。 |
5 | 用於簽署存取令牌的 com.nimbusds.jose.jwk.source.JWKSource 實例。 |
6 | java.security.KeyPair 實例,其中包含啟動時產生的金鑰,用於建立上述的 JWKSource 。 |
7 | 用於解碼已簽署存取令牌的 JwtDecoder 實例。 |
8 | 用於組態 Spring Authorization Server 的 AuthorizationServerSettings 實例。 |