1. 概述
在 Web 開發中,遇到錯誤是很常見的現象。其中一種錯誤是 HTTP 403 禁止錯誤。
在本教程中,我們將學習如何解決 Spring Boot POST 請求中的 403 錯誤。我們首先將瞭解 403 錯誤的意思,然後探索在 Spring Boot 應用程序中解決它的步驟。
2. 403 錯誤是什麼?
HTTP 403 錯誤,通常被稱為“禁止訪問”錯誤,是一種狀態碼,表明服務器已收到請求,但已選擇不進行授權。這通常意味着客户端缺乏訪問請求資源的權限。
需要注意的是,此錯誤與 401 錯誤不同,401 錯誤表明服務器需要驗證客户端,但尚未收到有效的憑據。
3. 403 錯誤原因
以下是 Spring Boot 應用程序中可能導致 403 錯誤的幾個因素。其中之一是在客户端未能提供身份驗證憑據時。在這種情況下,由於服務器無法驗證客户端的權限,因此服務器會拒絕請求,從而導致 403 錯誤。
另一個可能的原因在於服務器配置。例如,服務器可能已配置為拒絕來自某些 IP 地址或用户代理的請求,作為安全措施。如果請求來自這些被阻止的實體,服務器將返回 403 錯誤。
此外,Spring Security 默認啓用跨站請求偽造 (CSRF) 保護。CSRF 是一種攻擊,通過欺騙受害者提交惡意請求,並利用受害者的身份在他們的代表上執行不需要的功能。如果用於保護這種攻擊類型的 CSRF 令牌丟失或不正確,服務器也可能返回 403 錯誤。
4. 項目設置
為了演示如何解決 403 錯誤,我們將創建一個帶有 spring-boot-starter-web 和 spring-boot-starter-security 依賴的 Spring Boot 項目:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>然後,我們將創建一個控制器類來處理 POST 請求:
@PostMapping("/test-request")
public ResponseEntity<String> testPostRequest() {
return ResponseEntity.ok("POST request successful");
}上述方法具有 @PostMapping 註解,這意味着它可以處理向服務器的 POST 請求。成功的 POST 請求將返回 “POST 請求成功” 作為響應。
接下來,我們將通過添加一個內存用户配置 Spring Security:
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withUsername("user")
.password(encoder().encode("userPass"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public PasswordEncoder encoder() {
return new BCryptPasswordEncoder();
}在上述代碼中,我們配置應用程序使用內存用户進行請求身份驗證。該用户的密碼使用 BCryptPasswordEncoder 進行編碼,以增強安全性。
最後,我們將配置 SecurityFilterChain 以接受所有傳入的請求:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest()
.permitAll());
return http.build();
}本代碼片段配置應用程序,允許所有傳入請求,無需任何形式的身份驗證。
5. 解決 Spring Boot POST 請求中的 403 錯誤
本節將探討可能導致 403 錯誤的幾個因素,並討論可能的解決方案。
5.1. 跨站請求偽造 (CSRF) 防護
Spring Security 默認啓用了 CSRF 防護功能。如果請求頭中缺少 CSRF 令牌,服務器將返回 403 錯誤。這種行為不限於任何服務器環境,包括 localhost、測試環境或生產環境。
讓我們嘗試發起一個 POST 請求:
$ curl -X POST -H "Content-Type: application/json" http://localhost:8080/test-request請求以上導致返回禁止錯誤:
{"timestamp":"2023-06-24T16:52:05.397+00:00","status":403,"error":"Forbidden","path":"/test-request"}我們可以通過禁用 CSRF 保護來解決此錯誤。
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest()
.permitAll())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}在上述代碼中,我們通過調用 disable() 方法來禁用 CSRF 保護。
讓我們向 “/test-request” 端點發送一個 POST 請求:
$ curl -X POST -H "Content-Type: application/json" http://localhost:8080/test-request在禁用 CRSF 後,我們發送一個 POST 請求,服務器返回預期的 HTTP 響應:“POST 請求成功。”
然而,請注意,在生產環境中禁用 CRSF 保護通常不建議。CRSF 保護是防止跨站偽造攻擊的關鍵安全措施。因此,建議在狀態改變操作的請求頭中包含 CRSF 令牌。
5.2. 身份驗證憑據
向安全的端點提供錯誤的身份驗證憑據,或未提供身份驗證憑據,可能導致 Spring Boot 應用程序返回 403 錯誤。
讓我們修改 SecurityFilterChain 以驗證所有對服務器的請求:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authorizeRequests -> authorizeRequests.anyRequest()
.authenticated())
.httpBasic(withDefaults())
.formLogin(withDefaults())
.csrf(AbstractHttpConfigurer::disable);
return http.build();
}在上述代碼中,我們配置了應用程序在授予訪問權限之前對每個請求進行身份驗證。如果我們在不提供正確的身份驗證憑據的情況下向端點發送 POST 請求,則服務器將返回 403 錯誤。
讓我們使用我們創建的內存用户憑據向“/test-request”端點發送 POST 請求:
如上圖所示,當我們提供正確的身份驗證時,服務器將返回 200 OK 狀態碼。
6. 結論
在本文中,我們學習瞭如何通過禁用 CRSF 保護並提供正確的身份驗證憑據來解決 Spring Boot 中的 403 錯誤。我們還演示瞭如何配置 Spring Security 以接受經過身份驗證和未經過身份驗證的請求。此外,我們還強調了 Spring Boot 應用程序中 403 錯誤的各種原因。