@PreAuthorize 停止传播安全检查评估期间抛出的异常
@PreAuthorize stops propagating exceptions thrown during evaluation of security checks
我有一个带有多个端点的控制器。每个端点都映射到一个可以 return 200 或抛出异常的服务,然后处理该服务并将 return 正确的错误消息。
例如,如果未找到用户,我会抛出一个 UserNotFoundException
,然后它会被 ControllerAdvisor 捕获,并在 404 not found 中映射它。
一切正常,直到我添加了@PreAuthorize。它看起来像这样:
@PreAuthorize("@userController.userService.getUser(#userId).username == authentication.principal.name")
问题是,如果 getUser
抛出异常,我得到 500 而不是 404。
堆栈跟踪如下所示:
java.lang.IllegalArgumentException: Failed to evaluate expression '@userController.userService.getUser(#userId).username == authentication.principal.name'
at ...
Caused by: org.springframework.expression.ExpressionInvocationTargetException: A problem occurred when trying to execute method 'getUser' on object of type ...
at ...
Caused by: UserNotFoundException
所以看起来问题是由 UserNotFoundException
引起的,PreAuthorize
实现没有正确地重新抛出它。
这看起来是一个典型的场景,但我研究了很多,但没有找到任何解决方案。找不到用户时如何获取我的 404?
在这种情况下使用 @PreAuthorize
没有任何额外好处。
只需将您的 UserNotFoundException
放入您的业务逻辑中,并将此异常映射到您的 ControllerAdvisor
中的 404
,就像您之前所做的那样。
我有一个带有多个端点的控制器。每个端点都映射到一个可以 return 200 或抛出异常的服务,然后处理该服务并将 return 正确的错误消息。
例如,如果未找到用户,我会抛出一个 UserNotFoundException
,然后它会被 ControllerAdvisor 捕获,并在 404 not found 中映射它。
一切正常,直到我添加了@PreAuthorize。它看起来像这样:
@PreAuthorize("@userController.userService.getUser(#userId).username == authentication.principal.name")
问题是,如果 getUser
抛出异常,我得到 500 而不是 404。
堆栈跟踪如下所示:
java.lang.IllegalArgumentException: Failed to evaluate expression '@userController.userService.getUser(#userId).username == authentication.principal.name'
at ...
Caused by: org.springframework.expression.ExpressionInvocationTargetException: A problem occurred when trying to execute method 'getUser' on object of type ...
at ...
Caused by: UserNotFoundException
所以看起来问题是由 UserNotFoundException
引起的,PreAuthorize
实现没有正确地重新抛出它。
这看起来是一个典型的场景,但我研究了很多,但没有找到任何解决方案。找不到用户时如何获取我的 404?
在这种情况下使用 @PreAuthorize
没有任何额外好处。
只需将您的 UserNotFoundException
放入您的业务逻辑中,并将此异常映射到您的 ControllerAdvisor
中的 404
,就像您之前所做的那样。