1. 概述
在本教程中,我們將探討 Spring Boot 對安全性的強定義方法。
簡單來説,我們將重點關注默認的安全配置以及如果需要,如何禁用或自定義它。
2. 默認安全設置
為了為我們的 Spring Boot 應用程序添加安全性,我們需要添加 安全啓動器依賴
org.springframework.boot
spring-boot-starter-security
這將還包括 SecurityAutoConfiguration 類,其中包含初始/默認的安全配置。
請注意,我們沒有在此處指定版本,假設項目已使用 Boot 作為父項目。
默認情況下,身份驗證已啓用對於應用程序。 此外,內容協商用於確定是否應使用基本身份驗證或表單身份驗證。
有幾個預定義屬性:
spring.security.user.name
spring.security.user.password
如果我們不使用預定義屬性 spring.security.user.password 配置密碼,並啓動應用程序,則默認密碼將在控制枱日誌中隨機生成並打印:
使用默認安全密碼:c8be15de-4488-4490-9dc6-fab3f91435c6
有關更多默認值,請參閲 Spring Boot 常用應用程序屬性 參考頁面。
<(),
如果我們選擇了禁用自動配置安全選項,那麼我們自然需要提供自己的配置。 正如我們之前討論的,這是默認的安全配置。然後我們通過修改屬性文件對其進行自定義。 例如,我們可以通過添加自己的密碼來覆蓋默認密碼: 如果我們想要更靈活的配置,例如具有多個用户和角色,那麼我們需要使用完整的 @Configuration 類: @EnableWebSecurity 標註對於我們禁用默認安全配置至關重要。 如果缺少它,應用程序將無法啓動。 此外,請注意,我們 在 Spring Boot 2 中設置密碼時需要使用 PasswordEncoder。有關更多詳細信息,請參閲 Spring Security 5 中默認密碼編碼器指南。 現在,我們應該通過進行幾次快速測試來驗證我們的安全配置是否正確應用: Spring Security 實際上位於 Spring Boot Security 之後,因此可以使用此配置或其支持的任何集成來實現的任何安全配置也可以在 Spring Boot 中實現。 Spring Boot 具有專門的自動配置支持用於 OAuth2。 Spring Boot 1.x 中提供的 Spring Security OAuth 支持在後續的 boot 版本中被移除,取而代之的是內置的 OAuth 支持,該支持與 Spring Security 5 捆綁在一起。 我們將在下一部分中瞭解如何使用它。 對於舊版堆棧(使用 Spring Security OAuth),我們首先需要添加 Maven 依賴項以開始設置應用程序: 此依賴項包含一組可以觸發 OAuth2AutoConfiguration 類中定義的自動配置機制的類。 現在我們有多種選擇,具體取決於應用程序的範圍。 如果我們的應用程序希望成為 OAuth2 提供方,我們可以使用 @EnableAuthorizationServer。 在啓動時,我們會注意到在日誌中,自動配置類將生成授權服務器的客户端 ID 和客户端密鑰,以及基本的身份驗證所需的隨機密碼: 可以使用這些憑據獲取訪問令牌: 我們的其他文章提供了有關此主題的更多詳細信息。 還有其他用例由 Spring Boot OAuth2 覆蓋: 如果我們的應用程序需要成為這些類型之一,我們只需在應用程序屬性中添加一些配置,如鏈接中所述。 所有 OAuth2 相關的屬性可以在 Spring Boot 常用應用程序屬性 中找到。 為了使用 New Stack,我們需要根據我們想要配置的內容添加依賴項——一個授權服務器、資源服務器或客户端應用程序。 讓我們逐個查看它們。 正如我們所見,Spring Security OAuth 堆棧提供了將授權服務器設置為 Spring Application 的可能性。但是,該項目已被棄用,Spring 截至目前不支持自己的授權服務器。相反,建議使用像 Okta、Keycloak 和 ForgeRock 這樣的成熟提供商。 但是,Spring Boot 使我們能夠輕鬆配置這些提供商。例如,對於 Keycloak 配置,可以參考《使用 Keycloak 與 Spring Boot 的快速指南》或《Keycloak 在 Spring Boot 應用程序中的嵌入式》。 要包含資源服務器的支持,我們需要添加此依賴項: 要獲取最新版本的有關信息,請訪問 Maven Central。 此外,在我們的安全配置中,我們需要包含 oauth2ResourceServer() DSL: 我們的 OAuth 2.0 資源服務器與 Spring Security 5 提供了一個深入瞭解該主題的視角。 與我們配置資源服務器的方式類似,客户端應用程序也需要其依賴項和 DSL。 以下是 OAuth2 客户端支持的特定依賴項: 最新版本可以在 Maven Central 找到。 Spring Security 5 還通過其 oath2Login() DSL 提供了第一流的登錄支持。 有關新堆棧中 SSO 支持的詳細信息,請參閲我們的文章《簡單單點登錄與 Spring Security OAuth2》。 在本文中,我們重點介紹了 Spring Boot 提供的默認安全配置。我們看到了安全自動配置機制可以被禁用或覆蓋。然後我們研究瞭如何應用新的安全配置。4. 配置 Spring Boot 安全性
spring.security.user.password=password@Configuration
@EnableWebSecurity
public class BasicConfiguration {
@Bean
public InMemoryUserDetailsManager userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.withUsername("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
UserDetails admin = User.withUsername("admin")
.password(passwordEncoder.encode("admin"))
.roles("USER", "ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(request -> request.anyRequest()
.authenticated())
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
return encoder;
}
}@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class BasicConfigurationIntegrationTest {
TestRestTemplate restTemplate;
URL base;
@LocalServerPort int port;
@Before
public void setUp() throws MalformedURLException {
restTemplate = new TestRestTemplate("user", "password");
base = new URL("http://localhost:" + port);
}
@Test
public void whenLoggedUserRequestsHomePage_ThenSuccess()
throws IllegalStateException, IOException {
ResponseEntity<String> response =
restTemplate.getForEntity(base.toString(), String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response.getBody().contains("Baeldung"));
}
@Test
public void whenUserWithWrongCredentials_thenUnauthorizedPage()
throws Exception {
restTemplate = new TestRestTemplate("user", "wrongpassword");
ResponseEntity<String> response =
restTemplate.getForEntity(base.toString(), String.class);
assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
assertTrue(response.getBody().contains("Unauthorized"));
}
}5. Spring Boot OAuth2 Auto-Configuration (Using Legacy Stack)
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
5.1. OAuth2 授權服務器自動配置
使用默認安全密碼: a81cb256-f243-40c0-a585-81ce1b952a98
security.oauth2.client.client-id = 39d2835b-1f87-4a77-9798-e2975f36972e
security.oauth2.client.client-secret = f1463f8b-0791-46fe-9269-521b86c55b71
curl -X POST -u 39d2835b-1f87-4a77-9798-e2975f36972e:f1463f8b-0791-46fe-9269-521b86c55b71
-d grant_type=client_credentials
-d username=user
-d password=a81cb256-f243-40c0-a585-81ce1b952a98
-d scope=write http://localhost:8080/oauth/token
5.2. 其他 Spring Boot OAuth2 自動配置設置
6. Spring Boot OAuth2 Auto-Configuration (使用 New Stack)
6.1. OAuth2 授權服務器支持
6.2. OAuth2 資源服務器支持
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
@Configuration
public class JWTSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
...
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
...
}
}
6.3. OAuth2 客户端支持
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
7. 結論