每个组织的Spring Security用户角色

时间:2012-06-04 00:16:15

标签: grails spring-security

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

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

  • UserA具有OrganizationA的角色ROLE_ADMIN
  • UserA具有OrganizationB
  • 的角色ROLE_USER

我需要确保当UserA访问OrganizationB的资源时,他没有将其作为ADMIN。所以我需要额外检查用户是否在组织级别具有正确的角色。 Spring Security中是否有任何内容允许这样做?如果没有,有谁知道解决这个问题的最佳方法是什么?

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

我假设您可以根据他们选择的组织区分用户的角色。

基本上,您将编写标准RoleVoter的扩展版本,该版本会考虑组织。

答案 1 :(得分:1)

我想我已经很晚了,但这对我有用:

选择组织后,您可以在会话中设置具有新角色的新Authentication对象(先前的Authentication对象将失效)。像这样:

@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
}