2

我在我的应用程序中实现安全性时遇到问题......我有自定义身份验证并使用 @PreAuthorize 来处理我的用户授权。这工作正常。现在我想为每个用户实现访问控制,这意味着在我的应用程序中,当两个用户“Admin”和“John”可以调用方法时

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

'Admin' 可以对所有 Student 实例使用此方法,但 'John' 只能看到他的同学!所有用户都可以调用此方法(@PreAuthorize 不适合)但他们的访问权限是有限的怎么做?现在有通用方法吗?

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

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

什么是最好的解决方案???

4

2 回答 2

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@PostFilterACL 中将调用hasPermissionin MyPermissionEvaluatorfilterObject指列表中的单个项目。无论您的代码在哪里返回 false,它都会从列表中删除该项目。

于 2017-03-01T09:04:55.880 回答
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
    }
}
于 2017-03-01T08:55:09.107 回答