ผมอยากจะให้แก้ปัญหาบนพื้นฐานของคำตอบของ @kopelitsa ความแตกต่างที่สำคัญคือ:
- การนำการจัดการข้อยกเว้นของคอนโทรลเลอร์กลับมาใช้ใหม่โดยใช้
HandlerExceptionResolver
.
- การใช้ Java config ผ่าน XML config
ขั้นแรกคุณต้องตรวจสอบให้แน่ใจว่าคุณมีคลาสที่จัดการข้อยกเว้นที่เกิดขึ้นใน RestController / Controller ปกติ (คลาสที่มีคำอธิบายประกอบ@RestControllerAdvice
หรือ@ControllerAdvice
และวิธีการที่มีคำอธิบายประกอบ@ExceptionHandler
) สิ่งนี้จัดการข้อยกเว้นของคุณที่เกิดขึ้นในคอนโทรลเลอร์ นี่คือตัวอย่างการใช้ RestControllerAdvice:
@RestControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorDTO processRuntimeException(RuntimeException e) {
return createErrorDTO(HttpStatus.INTERNAL_SERVER_ERROR, "An internal server error occurred.", e);
}
private ErrorDTO createErrorDTO(HttpStatus status, String message, Exception e) {
(...)
}
}
หากต้องการใช้ลักษณะการทำงานนี้ซ้ำในห่วงโซ่ตัวกรอง Spring Security คุณต้องกำหนดตัวกรองและต่อเข้ากับการกำหนดค่าความปลอดภัยของคุณ ตัวกรองจำเป็นต้องเปลี่ยนเส้นทางข้อยกเว้นไปยังการจัดการข้อยกเว้นที่กำหนดไว้ข้างต้น นี่คือตัวอย่าง:
@Component
public class FilterChainExceptionHandler extends OncePerRequestFilter {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (Exception e) {
log.error("Spring Security Filter Chain Exception:", e);
resolver.resolveException(request, response, null, e);
}
}
}
จากนั้นตัวกรองที่สร้างขึ้นจะต้องถูกเพิ่มไปยัง SecurityConfiguration คุณต้องต่อมันเข้ากับโซ่ตั้งแต่เนิ่นๆเพราะจะไม่พบข้อยกเว้นของตัวกรองก่อนหน้าทั้งหมด ในกรณีของฉันมันสมเหตุสมผลที่จะเพิ่มก่อนหน้าไฟล์LogoutFilter
. ดูห่วงโซ่กรองเริ่มต้นและการสั่งซื้อของในเอกสารอย่างเป็นทางการ นี่คือตัวอย่าง:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private FilterChainExceptionHandler filterChainExceptionHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(filterChainExceptionHandler, LogoutFilter.class)
(...)
}
}