带有@Preauthorize 和@@ControllerAdvice 的自定义错误消息 [英] Custom Error message with @Preauthorize and @@ControllerAdvice

查看:94
本文介绍了带有@Preauthorize 和@@ControllerAdvice 的自定义错误消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用的是 spring 和 spring-security-3.2.最近我们在 RestAPIs 中添加了 @PreAuthorize 注解(之前是基于 URL 的).

We are using spring and spring-security-3.2. Recently We are adding annotations @PreAuthorize to RestAPIs(earlier it was URL based).

     @PreAuthorize("hasPermission('salesorder','ViewSalesOrder')")
  @RequestMapping(value = "/restapi/salesorders/", method = RequestMethod.GET)
  public ModelAndView getSalesOrders(){}

我们已经有了用 - @ControllerAdvice 和自定义 PermissionEvaluator 注释的全局异常处理程序,除了错误消息外,一切正常.

We already have Global exception handler which annotated with - @ControllerAdvice and custom PermissionEvaluator in place, everything works fine except the error message.

假设某些用户正在访问 API,但没有ViewSalesOrder"权限,然后默认情况下 spring 会抛出异常访问被拒绝",但没有说明缺少哪个权限(这是我们要求提及缺少哪个权限的要求)).

Lets say some user is accessing API At moment without having 'ViewSalesOrder' permission then spring by default throws the exception 'Access is denied',but didn't tell which permission is missing (Its our requirement to mention which permission is missing).

是否有可能抛出一个包含权限名称的异常,所以最终的错误消息应该是访问被拒绝,您需要 ViewSalesOrder 权限"(这里的权限名称应该来自@PreAuthorize 注释)?

Is it possible to throw an exception which also include the permission name, so final error message should be look like "Access is denied, you need ViewSalesOrder permission"(here permission name should be from @PreAuthorize annotation)?

请注意,我们有 100 个这样的 restAPI,因此非常感谢通用解决方案.

Please note that we have 100 such restAPI in place so generic solution will be highly appreciated.

推荐答案

没有很好的方法来实现您的期望,因为 PermissionEvaluator 接口不允许您将缺少的权限与结果一起传递的评价.
此外,AccessDecisionManager 根据 AccessDecisionVoter 实例的投票决定最终授权,其中之一是 PreInvocationAuthorizationAdviceVoter@PreAuthorize 值的评估.

长话短说,当您的自定义 PermissionEvaluatorfalse 返回给 hasPermission 调用.如您所见,无法在此流程中传播失败的原因.

There is no pretty way of achieving what you expect since PermissionEvaluator interface doesn't let you pass the missing permission along with the result of the evaluation.
In addition, AccessDecisionManager decides on the final authorization with respect to the votes of the AccessDecisionVoter instances, one of which is PreInvocationAuthorizationAdviceVoter which votes with respect to the evaluation of @PreAuthorize value.

Long story short, PreInvocationAuthorizationAdviceVoter votes against the request (giving the request –1 point) when your custom PermissionEvaluator returns false to hasPermission call. As you see there is no way to propagate the cause of the failure in this flow.

另一方面,您可以尝试一些变通办法来实现您想要的.

一种方法是在权限检查失败时在您的自定义 PermissionEvaluator 中抛出异常.您可以使用此异常将缺少的权限传播到您的全局异常处理程序.在那里,您可以将缺少的权限作为参数传递给您的消息描述符.请注意,这将停止 AccessDecisionManager 的执行过程,这意味着不会执行后续的投票者(默认为 RoleVoterAuthenticatedVoter).如果你选择走这条路,你应该小心.

另一种更安全但更笨拙的方法是实现自定义 AccessDeniedHandler 并在响应 403 之前自定义错误消息.AccessDeniedHandler 为您提供当前可以使用的 HttpServletRequest检索请求 URI.但是,在这种情况下的坏消息是,您需要一个到权限映射的 URI 才能定位丢失的权限.

On the other hand, you may try some workarounds to achieve what you want.

One way can be to throw an exception within your custom PermissionEvaluator when permission check fails. You can use this exception to propagate the missing permission to your global exception handler. There, you can pass the missing permission to your message descriptors as a parameter. Beware that this will halt execution process of AccessDecisionManager which means successive voters will not be executed (defaults are RoleVoter and AuthenticatedVoter). You should be careful if you choose to go down this path.

Another safer but clumsier way can be to implement a custom AccessDeniedHandler and customize the error message before responding with 403. AccessDeniedHandler provides you current HttpServletRequest which can be used to retrieve the request URI. However, bad news in this case is, you need a URI to permission mapping in order to locate the missing permission.

这篇关于带有@Preauthorize 和@@ControllerAdvice 的自定义错误消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆