2

在我的应用程序中,我有一个名为组织的顶级实体。用户和组织之间的关系是多对多的。

因此,我可能会遇到以下情况:

  • 用户 A 具有组织 A 的角色 ROLE_ADMIN
  • 用户 A 具有组织 B 的角色 ROLE_USER

我需要确保当用户 A 访问组织 B 的资源时,他不是以管理员身份进行操作。因此,我需要额外检查用户是否在组织级别具有正确的角色。Spring Security 中是否有任何内置功能允许这样做?如果没有,有谁知道解决这个问题的最佳方法是什么?

更新:更多信息......

用户登录并选择他们想要使用的组织。那存储在会话中。除此之外,URL 被 Secured 注释锁定。这意味着如果 UserA 登录并选择 OrgA,他们应该能够访问 /admin/user/create,但是,如果他们登录并选择 OrgB,他们不应该访问该 URL。

漫长的道路是在每个重要的方法中添加额外的检查。所以调用一些服务方法,上面写着“好的,你是 OrgA 的管理员,但不是 OrgB 的管理员,并且你使用 OrgB 登录,所以拒绝这个请求”。

我希望有一种更多的 grails / spring-security 方式来处理这个问题。

4

2 回答 2

2

您可能可以通过使用自定义AccessDecisionVoter. 该vote方法将为您提供资源(方法或 URL)的“配置属性”,这通常是所需的角色,您可以直接从Authentication对象获取当前用户的角色/权限,或者通过读取当前组织并为用户选择适当的角色。

我假设您有某种方法可以根据他们选择的组织来区分用户的角色。

从本质上讲,您将编写标准的扩展版本,该版本RoleVoter将组织考虑在内。

于 2012-06-06T14:52:30.900 回答
1

我想我来晚了,但这对我有用:

选择组织后,您可以在会话中设置具有新角色的新身份验证对象(之前的身份验证对象无效)。像这样的东西:

@RequestMapping(value = "/org-a")
String orgA(HttpServletRequest request) {
    request.getSession().setAttribute("org", "org-a")
    Organization org = new Organization("org-a")
    reloadRolesForAuthenticatedUser(org)
    ....
}

private void reloadRolesForAuthenticatedUser(Organization org) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication()
    List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), org)
    List<GrantedAuthority> authorities = getAuthorities(newRoles)
    Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
    SecurityContextHolder.getContext().setAuthentication(newAuth)
}


private List<GrantedAuthority> getAuthorities(List<String> roles) {
    List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
    if (!roles.isEmpty()) {
        for (String r : roles) {
            auths.add(new SimpleGrantedAuthority(r))
        }
    }
    return auths
}
于 2017-07-17T23:33:00.353 回答