在我的网络安全配置中,我明确设置了一个访问被拒绝的处理程序,如下所示:
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.addFilterBefore(devProfileFilter, UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(customAuthenticationFilter, DevProfileFilter.class)
.authorizeRequests()
.antMatchers("/users/**").hasAuthority("ROLE_ADMIN")
.antMatchers("/upload/**").hasAuthority("ROLE_SUBMITTER")
.antMatchers("/download/**").hasAuthority("ROLE_REQUESTER")
.antMatchers("/api/**", "/swagger-ui.html").hasAuthority("ROLE_APIACCESS")
.anyRequest()
.authenticated() // All requests need authentication through RP
.and()
.headers()
.frameOptions()
.deny()
.and()
.csrf() // Enable CSRF protection (enabled by default)
.and()
.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) ->
{
// Set response status
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
// Throw the exception to be caught by the GlobalExceptionHandler
throw accessDeniedException;
});
然后我像这样定义了一个全局异常处理程序类:
@ControllerAdvice
public class GlobalExceptionHandler
{
@Autowired
private ForbiddenAccessRepository forbiddenAccessRepository;
@ExceptionHandler(AccessDeniedException.class)
public ModelAndView handleAccessDeniedException(AccessDeniedException ex, HttpServletRequest request, Model model) {
int status = HttpStatus.FORBIDDEN.value();
model.addAttribute("status", status);
model.addAttribute("exception", ex.getMessage());
// Log forbidden access
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getPrincipal() instanceof User) {
User user = (User) auth.getPrincipal();
ForbiddenAccess forbiddenAccess = new ForbiddenAccess();
forbiddenAccess.setBemsid(user.getBemsid());
forbiddenAccess.setPage(request.getRequestURI());
forbiddenAccess.setAccessTime(LocalDateTime.now());
ForbiddenAccess saved = forbiddenAccessRepository.save(forbiddenAccess);
System.out.println("Saved ForbiddenAccess: " + saved);
}
System.out.println("Access Denied Exception Handled: Status = " + status);
return new ModelAndView("error");
}
// TODO: Replace with specifically handled exceptions.
// Catch-all for any other exceptions not handled above
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex, Model model) {
model.addAttribute("status", HttpStatus.INTERNAL_SERVER_ERROR);
model.addAttribute("exception", ex.getMessage());
return new ModelAndView("error");
}
}
我预计,如果我试图在没有适当角色的情况下访问 Web 应用程序的一部分,我的安全配置会抛出 403 错误,并由我的全局异常处理程序接收。
但是我没有在全局异常处理程序中触发任何断点或打印语句。相反,相应的错误页面 (error.html) 正在显示,但显示 500 错误并且我没有插入到我的禁止访问存储库中。
编辑:我更新了我的 Spring Security 配置中的 .exceptionHandling() 方法,现在 999 渗透到顶部,但仍然没有断点触发或来自全局异常处理程序的数据库插入。
.and()
.exceptionHandling()
.accessDeniedHandler(new AccessDeniedHandler()
{
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException
{
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getPrincipal() instanceof User)
{
User user = (User) auth.getPrincipal();
ForbiddenAccess forbiddenAccess = new ForbiddenAccess();
forbiddenAccess.setBemsid(user.getBemsid());
forbiddenAccess.setPage(request.getRequestURI());
forbiddenAccess.setAccessTime(LocalDateTime.now());
forbiddenAccessRepository.save(forbiddenAccess);
}
// Set response status
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
// add status to the request
request.setAttribute("status", HttpServletResponse.SC_FORBIDDEN);
// forward to error page
request.getRequestDispatcher("/error").forward(request, response);
}
});