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 請求成功");
}
上述方法具有@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 保護。如果請求頭中缺少 CRSF 令牌,則服務器將返回 403 錯誤。此行為不適用於任何服務器環境,包括 localhost、staging 和 production。
讓我們嘗試發送一個 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();
}
在上面的代碼中,我們配置了應用程序在授予訪問權限之前驗證每個請求。
讓我們使用我們創建的內存用户憑據向“/test-request”端點發送一個 POST 請求:
上面的圖像顯示,當我們提供正確的身份驗證憑據時,服務器返回 200 OK 狀態代碼。
6. 結論
在本文中,我們學習瞭如何通過禁用 CRSF 保護並提供正確的身份驗證憑據來解決 Spring Boot 中的 403 錯誤。我們還演示瞭如何配置 Spring Security 以接受經過身份驗證和未經過身份驗證的請求。此外,我們還強調了 Spring Boot 應用程序中 403 錯誤的各種原因。