Spring 安全 ACL - 允许用户 'read' 来自域 class 的一个字段

Spring Security ACL - Allow Users to 'read' one field from the Domain class

我是 Spring 安全框架的新手,这里有一个小问题需要解决。

我已经成功地将@PreAuthorized("hasPermission('#person', Permission) 注释用于服务和控制器方法。 这对我来说很好,但这只适用于整个域 class.

在我的例子中,有一些字段应该显示给用户,尽管他们没有阅读这个人的权限。

一个简单的例子:

  1. 用户登录。
  2. 他想访问 Jon Doe 的个人资料页面。
  3. 但是用户没有阅读 Jon Doe 的权限。
  4. 系统应该通知用户他没有权限并显示 名称如:您无权阅读 Jon Doe 的个人资料。"

这是一个非常简单的示例,用户可以看到更多字段。

希望您能理解我的要求。

(抱歉我的英文不是很好。)

编辑

个人控制器

 @RequestMapping("/{id}")
 public String get(@PathVariable("id") Long personId, Model model,HttpSession session) {

    Person person = personService.findById(personId);

    /* DO STUFF HERE */

    return "person.show";
}

个人服务

@PreAuthorize("hasPermission('#personId', <domainClass>, 'read')")
public Person findById(Long personId) {
    return personRepository.findOne(personId);
}

您可以完全不使用 @PreAuthorized("hasPermission('#person', Permission) 注释,而是在您的代码中 手动 来明确地做到这一点……但这会部分损害利益使用 Spring 安全框架 !

我建议:

  • 在服务 class 层中使用 @PreAuthorized("hasPermission('#person', Permission) 注释 => 它应该抛出一个 AccessDeniedException 是不允许用户读取该配置文件
  • 在调用控制器中为 AccessDeniedException 添加处理程序。由于在执行控制器方法期间会抛出异常,因此该处理程序将有机会处理它。从相关服务 class 调用一个非受保护的方法,该方法只会 return public 字段并转发到一个视图,指示 您没有读取配置文件的权限来自 Jon Doe

在该配置中,异常处理程序应采用与原始控制器方法等效的参数才能访问:

  • Principal 执行请求
  • 所请求配置文件的 ID

但这应该不是问题,因为除了异常本身之外,异常处理程序还可以接受与 @RequestMapping 方法几乎相同的参数。

根据您的编辑,您会从路径变量中获得 personId,这很难从异常处理程序中获得。所以你应该在调用受保护的服务方法之前将它保存为请求属性以在异常处理程序中获取它:

 @RequestMapping("/{id}")
 public String get(@PathVariable("id") Long personId, Model model,HttpSession session, HttpServletRequest request) {

    request.setAttribute("personId", personId);
    Person person = personService.findById(personId);

    /* DO STUFF HERE */

    return "person.show";
} 

@ExceptionHandler(AccessDeniedException.class)
 public ModelAndView accessDeniedHandler(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView("accessDeniedView");
    Long personId = request.getAttribute("personId");
    // populate your model
    return mav;
}