Spring Security 如何自定义@PreAuthorize(“isAuthenticated()”)返回的http状态?

bxgwgixi  于 2024-01-09  发布在  Spring
关注(0)|答案(2)|浏览(562)

在一个spring Boot 控制器中,我使用@PreAuthorize("isAuthenticated()")来检查用户是否登录(使用基本auth + JSESSIONID)。
但是如果用户没有登录,即他们没有经过身份验证,控制器将返回403 Forbidden
根据我所知道的身份验证与授权,401用于身份验证,而403用于授权。
根据我的理解,@PreAuthorize()总是检查用户的授权(顾名思义),但是有没有什么方法可以根据我们传递给它的参数来定制它,比如这里的isAuthenticated()
我知道还有另一种解决方案:在configure(HttpSecurity httpSecurity)中使用基于URL的安全配置,但如果我不想这样做呢?
任何想法请。

q1qsirdb

q1qsirdb1#

当你用@Pre/PostAuthorize注解方法A时,spring将为这样的对象创建代理,并且每个对这样的方法的调用都将通过代理(如果对象在spring上下文下)。
@Pre/PostAuthorize的代理将从annotation中评估expression(这里很复杂),如果为true,则将请求父对象(传递给真实的方法),如果不为true,则抛出抛出DanieledException。您也可以在方法A中自己抛出这样的异常,效果也是一样的。这里讲的是@Pre/PostAuthorize如何工作,没有更多的魔力!
但这不是故事的结局!
如果AccessDaniedException没有被抑制或重新转换(没有堆栈,堆栈中没有AccessDaniedException),那么它将被Spring Security中的ExceptionTranslationFilter捕获,ExceptionTranslationFilter将查看用户是否经过身份验证

  • 如果是,则ExceptionTranslationFilter将委托给AccessDeniedHandler来处理这种情况,AccessDeniedHandler的默认实现将返回403http代码或重定向到错误页面取决于您是否使用rest。
  • 如果没有,那么ExceptionTranslationFilter将委托给AuthenticationEntryPoint,它将处理这种情况(重定向到登录页面,要求http基本.等)。

注意:ExceptionTranslationFilter将重新抛出异常,如果任何其他AuthenticationExceptionAccessDeniedException和可能500将显示:(

您的问题可能是另一个问题,请查看Spring Security anonymous 401 instead of 403

被抑制:(:

  1. @GetMapping(value = "/test/ok")
  2. public String getOk() {
  3. try {
  4. myService.securedMethod();
  5. return "ok";
  6. } catch (Exception e) {
  7. log.info("AccessDeniedException suppressed not rethrowing :(", e);
  8. return "error";
  9. }
  10. }

字符串
正确的重新翻译:):

  1. @GetMapping(value = "/test/ok")
  2. public String getOk() {
  3. try {
  4. myService.securedMethod();
  5. return "ok";
  6. } catch (AccessDeniedException e) {
  7. throw new MyException(e); //public MyException(Throwable cause)
  8. }
  9. }

展开查看全部
epggiuax

epggiuax2#

我也遇到了同样的问题,我用RestControllerAdviceExceptionHandler解决了这个问题

  1. @ExceptionHandler(AccessDeniedException.class)
  2. public Response<ErrorResponse> exception(AccessDeniedException exception, HttpServletResponse response) {
  3. Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  4. boolean isAuthenticated = !(authentication instanceof AnonymousAuthenticationToken);
  5. return error(
  6. isAuthenticated ? HttpStatus.FORBIDDEN.value() : HttpStatus.UNAUTHORIZED.value(),
  7. Collections.singleton(isAuthenticated ? exception.getMessage() : "Authentication is required"),
  8. exception,
  9. response
  10. );
  11. }

字符串

相关问题