java – Spring Security中Role和GrantedAuthority之间的区别

发布于 2019-01-17  500 次阅读


Spring Security中有一些概念和实现,例如授予授权/控制访问权限的GrantedAuthority接口。我想要允许操作,例如createSubUsers或deleteAccounts,我将允许一个管理员(角色为ROLE_ADMIN)。 我很困惑作为我在线看到的教程/演示。我试着连接我读的东西,但我认为我们可以互换。 我看到hasRole消耗GrantedAuthority字符串?我最明白的是做错了理解。 Spring Security中的概念是什么? 如何存储用户的角色,与该角色的权限分开? 我也在查看org.springframework.security.core.userdetails.UserDetails接口,它在认证提供者引用的DAO中使用,它消耗一个用户(注意最后一个GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)

还是有其他方法来区分另外两个?还是不支持,我们必须自己做? 将GrantedAuthority视为“权限”或“权限”。这些“权限”(通常)表示为字符串(使用getAuthority()方法)。这些字符串让你识别权限,让你的选民决定他们是否授予访问权限。您可以将不同的GrantedAuthority(权限)放入安全上下文中,以授予用户。你通常通过实现自己的UserDetailsS​​ervice来返回一个UserDetails实现,返回所需的GrantedAuthorities。 角色(因为它们在许多示例中使用)仅仅是具有命名约定的“权限”,该命名约定说角色是以前缀ROLE_开头的GrantedAuthority。没有什么了。角色只是GrantedAuthority – 一个“权限” – 一个“权利”。你看到很多的Spring安全的地方,其中ROLE_前缀的角色被特别处理为例如。在RoleVoter中,其中ROLE_前缀用作默认值。这允许您提供角色名称与ROLE_前缀。在Spring安全4之前,这种“角色”的特殊处理没有得到一致的遵守,并且权威和角色经常被视为相同(例如,您可以在SecurityExpressionRoot中的hasAuthority()方法的实现中看到这一点 – 只需调用hasRole ())。使用Spring Security 4,角色的处理更加一致,处理“角色”的代码(如RoleVoter,hasRole表达式等)总是为您添加ROLE_前缀。因此,hasAuthority(‘ROLE_ADMIN’)意味着与hasRole(‘ADMIN’)相同,因为ROLE_前缀会自动添加。有关更多信息,请参阅spring security 3 to 4 migration guide。 但是:角色只是一个具有特殊ROLE_前缀的权限。所以在Spring安全3 @PreAuthorize(“hasRole(‘ROLE_XYZ’)”)与@PreAuthorize(“hasAuthority(‘ROLE_XYZ’)”与@PreAuthorize(“hasAuthority(‘ROLE_XYZ’)”)相同。 关于您的用例:

Users have roles and roles can perform certain operations.

对于用户所属的角色和角色可以执行的操作,您可以在GrantedAuthorities中结束。角色的GrantedAuthorities具有前缀ROLE_,并且操作具有前缀OP_。操作权限的示例可以是OP_DELETE_ACCOUNT,OP_CREATE_USER,OP_RUN_BATCH_JOBetc。角色可以是ROLE_ADMIN,ROLE_USER等。 你可以最终让你的实体实现GrantedAuthority像这个(伪代码)例子:

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @OneToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @OneToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}

您在数据库中创建的角色和操作的ID将是GrantedAuthority表示,例如“ROLE_ADMIN”,“OP_DELETE_ACCOUNT”等。当用户通过身份验证时,请确保所有角色的所有GrantedAuthorities和相应的操作都从UserDetails.getAuthorities()方法返回。 例: ID为ROLE_ADMIN的管理角色具有分配给它的操作OP_DELETE_ACCOUNT,OP_READ_ACCOUNT,OP_RUN_BATCH_JOB。 具有标识ROLE_USER的用户角色具有操作OP_READ_ACCOUNT。 如果管理员登录的结果安全上下文将有GrantedAuthorities: ROLE_ADMIN,OP_DELETE_ACCOUNT,OP_READ_ACCOUNT,OP_RUN_BATCH_JOB 如果用户记录它,它将有: ROLE_USER,OP_READ_ACCOUNT UserDetailsS​​ervice将注意收集这些角色的所有角色和所有操作,并通过返回的UserDetails实例中的getAuthorities()方法使它们可用。


公交车司机终于在众人的指责中将座位让给了老太太