Spring Boot Security自訂拒絕存取處理器的方式如下。
範例環境:
- Spring Boot 2.2.1.RELEASE
- Spring Security 5.2.1.RELEASE
請先參考Spring Boot + Spring Security 基本配置設定教學進行Spring Security的設定。
當試圖存取Spring Security保護的資源但沒有權限時,預設是由AccessDeniedHandlerImpl
返回403 Forbidden錯誤。
如果要自訂拒絕存取時的處理邏輯,可新增一個類別實作AccessDeniedHandler
介面並覆寫handle(...)
方法,並在Spring Security配置類別中透過HttpSecurity.exceptionHandling()
取得ExceptionHandlingConfigurer
的實例,然後呼叫accessDeniedHandler()
來設定此類別為自訂拒絕存取處理器。
例如下面是本範例的自訂拒絕存取處理器DemoAccessDeniedHandler
。其實作AccessDeniedHandler
並設定了@Component
使其被掃描註冊為Bean。當使用者無存取權限時返回“YOU SHALL NOT PASS"訊息。
DemoAccessDeniedHandler
package com.abc.demo.config.security;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class DemoAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(
HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException e) throws IOException, ServletException {
response.getOutputStream().println("YOU SHALL NOT PASS!");
}
}
下面是範例專案的Spring Security配置類別DemoWebSecurityConfig
。@Autowired
注入DemoAccessDeniedHandler
的實例,並透過ExceptionHandlingConfigurer.accessDeniedHandler()
將該實例設為拒絕存取時的處理器。
此外在DemoWebSecurityConfig
類別名稱前加上@EnableGlobalMethodSecurity(securedEnabled = true)
來啟用方法安全防護@Security
功能。
DemoWebSecurityConfig
package com.abc.demo.config.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
@EnableGlobalMethodSecurity(securedEnabled = true) // 啟用Method Security @Security
@EnableWebSecurity
public class DemoWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
AccessDeniedHandler demoAccessDeniedHandler; // 注入自訂拒絕存取處理器的實例
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and().formLogin()
.and().httpBasic()
.and().exceptionHandling()
.accessDeniedHandler(demoAccessDeniedHandler); // 設定自訂拒絕存取處理器
}
}
然後在DemoController.demo()
方法前加上@Secured(value = "ROLE_ADMIN")
,則此方法必須要有ADMIN
權限才可存取,以此來測試DemoAccessDeniedHandler
的效果。
DemoController
package com.abc.demo.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@GetMapping(value = "/")
@Secured(value = "ROLE_ADMIN") // <--
public String demo() {
return "Spring Boot + Spring Security Configuration Demo";
}
}
最後進行測試。在本機啟動專案,在登入頁面以預設使用者登入並對http://localhost:8080/demo/
發出請求。由於登入的一般使用者並無ADMIN
權限,因此存取DemoController.demo()
會被拒絕存取,最終透過自訂拒絕存取處理器DemoAccessDeniedHandler
返回訊息。
參考:
沒有留言:
張貼留言