在spring boot控制器中,我正在使用@PreAuthorize("isAuthenticated()")
检查用户是否已登录(使用基本身份验证+ JSESSIONID
)。
但是,如果用户未登录,即未通过身份验证,则控制器将返回403 Forbidden
。
根据我对身份验证与授权的了解,401
用于身份验证,403
用于授权。
根据我的理解,@PreAuthorize()
始终检查用户的授权(如名称所示),但是有任何方法可以根据我们传递给它的参数(即isAuthenticated()
)对其进行自定义在这里?
我知道还有另一种解决方案:在configure(HttpSecurity httpSecurity)
中使用基于URL的安全性配置,但是如果我不想这样做,该怎么办。
请提出任何想法。
答案 0 :(得分:0)
当您使用@Pre/PostAuthorize
注释方法 A 时,spring将为该对象创建代理,并且对该方法的每次调用都将通过代理(如果对象在spring上下文中)。
@Pre/PostAuthorize
的代理将评估注释中的表达式(此处复杂),如果正确,则将请求父传递给请求方法(传递给真实方法),如果抛出AccessDaniedException 。您也可以在方法 A 中自己抛出此类异常,其效果将相同。这是关于@Pre/PostAuthorize
如何在这里不再起作用的一切!
但这还不是故事的结局!
如果AccessDaniedException
没有被抑制或重新转换(没有AccessDaniedException
的堆栈),那么它将在Spring Security中被ExceptionTranslationFilter
捕获,并且ExceptionTranslationFilter
将会看到如果用户已已认证
如果不是ExceptionTranslationFilter
,则将委托给AccessDeniedHandler
来处理这种情况,并且AccessDeniedHandler
的默认实现将返回 403 http代码或重定向进入错误页面取决于您是否正在使用休息状态。
如果不是,则ExceptionTranslationFilter
将委派给AuthenticationEntryPoint
并将处理这种情况(重定向到登录页面,要求提供http basic ...等)。
注意:如果显示ExceptionTranslationFilter
或AuthenticationException
以外的任何其他字符,并且可能显示 500 ,AccessDeniedException
将抛出异常:(
您的问题可能是另一个问题,请查看Spring Security anonymous 401 instead of 403
禁止显示:(:
@GetMapping(value = "/test/ok")
public String getOk() {
try {
myService.securedMethod();
return "ok";
} catch (Exception e) {
log.info("AccessDeniedException suppressed not rethrowing :(", e);
return "error";
}
}
正确重新翻译:):
@GetMapping(value = "/test/ok")
public String getOk() {
try {
myService.securedMethod();
return "ok";
} catch (AccessDeniedException e) {
throw new MyException(e); //public MyException(Throwable cause)
}
}