2017-03-01 57 views
2

我有一个问题在我的应用程序中实现安全性... 我有自定义身份验证并使用@PreAuthorize来处理我的用户授权。这工作正常。现在我想实现访问控制每个用户,这意味着我的应用程序时,两个用户,“管理员”和“约翰”,可以调用方法最佳实现'访问'用户在春季安全

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(@PathVariable long id) { 
    return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); 
} 

“管理员”可以使用此方法对所有学生的实例,但'约翰'只能看到他的同学! 所有的用户都可以调用这个方法(@PreAuthorize不适合),但是他们的访问是有限的。 现在有一般方法吗?

ACL是最好的方式?(有最好的例子吗?)

HDIV框架可以帮助我解决我的问题?

什么是最佳解决方案???

回答

1

分别将两个不同的角色分配给Admin和John ROLE_ADMIN,ROLE_USER。然后检查控制器中的角色,并调用相应的服务方法根据角色返回数据。

@RequestMapping(value = "/load/{id}", method = RequestMethod.GET) 
@ResponseBody 
public StudentYearViewModel load(HttpServletRequest request, Authentication authentication, @PathVariable long id) { 

    if (request.isUserInRole("ROLE_ADMIN")) { 
     return ModelMapper.map(iStudentService.loadByEntityId(id), StudentViewModel.class); //return all records 
    } if (request.isUserInRole("ROLE_USER")) { 
    String username = authentication.getName(); //get logged in user i.e. john 
     return ModelMapper.map(iStudentService.loadByEntityId(id, username), StudentViewModel.class); //return records by username 
    } 
} 
+0

感谢您的关注!我应该为所有学生创造许多角色....这是最好的解决方案!!? –

1

你想看看@PostFilter@PreFilter。他们的工作方式非常类似于@PreAuthorize,但可以从列表中删除结果。假设您还没有这样做,您还需要为用户分配不同的角色。

全局规则,像管理员能够看到的一切,你可以通过编写具体的实现PermissionEvaluator来实现。然后您将其添加到MethodSecurityExpressionHandler

一个简单示例的时间。

此代码是用文本编辑器编写的。它可能无法编译,并且只在这里表现得非常简单需要

一个步骤PermissionEvaluator

public class MyPermissionEvaluator implements PermissionEvaluator { 
    private static final SimpleGrantedAuthority AUTHORITY_ADMIN = new SimpleGrantedAuthority('admin'); 

    public boolean hasPermission(final Authentication authentication, final Object classId, final Object permission) { 
     boolean permissionGranted = false; 

     // admin can do anything 
     if (authentication.getAuthorities().contains(AUTHORITY_ADMIN)) { 
      permissionGranted = true; 
     } else { 
      // Check if the logged in user is in the same class 
     } 
     return permissionGranted; 
    } 

    @Override 
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, 
      Object permission) { 
     return false; 
    } 

} 

然后配置方法安全

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { 

    @Bean 
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler(final PermissionEvaluator permissionEvaluator){ 
     DefaultMethodSecurityExpressionHandler securityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); 
     securityExpressionHandler.setPermissionEvaluator(permissionEvaluator); 
     return securityExpressionHandler; 
    } 

    @Bean 
    public PermissionEvaluator permissionEvaluator() { 
     return new MyPermissionEvaluator(); 
    } 
} 

现在我们可以用我们的过滤器上的方法

@PostFilter("hasPermission(filterObject.getClassId(), 'READ')") 
@Override 
public List<Student> getAll() { 
    return querySomeStudents(); 
} 

hasPermission i n @PostFilter ACL将调用MyPermissionEvaluator中的hasPermissionfilterObject指的是列表中的单个项目。无论您的代码返回false,它都会从列表中删除该项目。

+0

谢谢!!你的解决方案好得多,但我有问题。 “filterObject.getClassId()”工作如何?这个表现是否好?这是最好的方式来获取所有列表而不是删除一个?我想如果我在DB中写这个过滤器是不行的? –

+0

'filterObject'是Spring使用内省获得的。表现是一个非常相对的术语。我在很多地方使用它,没有任何性能问题。我的感觉是写出最干净,最容易维护的代码,并在出现问题时解决性能问题。假设您已成功创建索引,从性能的角度来看,过滤数据库中的数据是“更好”的。在数据库上过滤也可以减少网络I/O。 – Leon