Spring Security可以自訂AccessDeniedHandler的實作來處理拒絕存取時的邏輯,Spring Boot應用程式可能也會利用@ControllerAdvice處理各種例外。今天發現當使用@ControllerAdvice捕捉最大的例外Exception時,自訂的AccessDeniedHandler無法作用。
請先參考Spring Boot Security 自訂拒絕存取處理器的設定,然後新增標註@ControllerAdvice的類別DemoControllerAdvice如下。
DemoControllerAdvice
package com.abc.demo.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class DemoControllerAdvice {
@ExceptionHandler({Exception.class})
public ResponseEntity exceptionHandler() {
return ResponseEntity.ok("Error!!");
}
}
則當存取無權限的API時變成由DemoControllerAdvice.exceptionHandler()返回以下結果,而非透過DemoAccessDeniedHandler。
原因是存取被拒時Spring Security會丟出AccessDeniedException例外,此例外屬於java.lang.Exception,而使用@ControllerAdvice處理Exception後,AccessDeniedException會先被DispatcherServlet.doDispatch()中的try catch捕捉。
若希望AccessDeniedException仍由AccessDeniedHandler處理,則可在DemoControllerAdvice中新增一個處理AccessDeniedException的方法,並再丟出新的AccessDeniedException。
DemoControllerAdvice
package com.abc.demo.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class DemoControllerAdvice {
@ExceptionHandler({AccessDeniedException.class})
public void accessDeniedExceptionHandler(AccessDeniedException e) {
throw new AccessDeniedException("Access denied");
}
@ExceptionHandler({Exception.class})
public ResponseEntity exceptionHandler(Exception e) {
return ResponseEntity.ok("Error!!");
}
}
參考:
沒有留言:
張貼留言