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!!");
}
}
參考:
沒有留言:
張貼留言