将授权视为"许可"或"权利".这些"权限"通常用字符串表示(使用getAuthority()
方法).通过这些字符串,您可以识别权限,并让您的投票人决定是否授予访问权限.
通过将用户放入安全上下文中,可以向用户授予不同的授权(权限).通常通过实现自己的UserDetails服务来实现,该服务返回一个UserDetails实现,该实现返回所需的授权.
角色(在许多示例中使用)只是"权限",其命名约定表示角色是以前缀ROLE_
开头的授权.没有别的了.角色只是一种授权——一种"许可"——一种"权利".在spring security中,有很多地方会专门处理带有ROLE_
前缀的角色,例如在RoleVoter中,ROLE_
前缀被用作默认值.这允许您提供前缀为ROLE_
的角色名称.在Spring security 4之前,对"角色"的这种特殊处理并没有得到非常一致的遵循,权限和角色通常被视为相同的(例如,您可以在SecurityExpressionRoot中实现hasAuthority()
方法中看到,它只是调用hasRole()
).在Spring Security 4中,角色的处理更加一致,处理"角色"的代码(如RoleVoter
、hasRole
表达式等)总是为您添加ROLE_
前缀.所以hasAuthority('ROLE_ADMIN')
和hasRole('ADMIN')
的意思相同,因为ROLE_
前缀会自动添加.更多信息请参见spring security 3至4 migration guide.
但话虽如此:角色只是一个带有特殊ROLE_
前缀的权威机构.因此,在Spring中,安全性3@PreAuthorize("hasRole('ROLE_XYZ')")
与@PreAuthorize("hasAuthority('ROLE_XYZ')")
相同,而在Spring中,安全性4@PreAuthorize("hasRole('XYZ')")
与@PreAuthorize("hasAuthority('ROLE_XYZ')")
相同.
关于您的用例:
用户有角色,角色可以执行某些操作.
对于一个用户所属的角色和一个角色可以执行的操作,最终可能会有GrantedAuthorities
个.角色的GrantedAuthorities
具有前缀ROLE_
,操作具有前缀OP_
.运营机构的一个例子可能是OP_DELETE_ACCOUNT
、OP_CREATE_USER
、OP_RUN_BATCH_JOB
等.角色可以是ROLE_ADMIN
、ROLE_USER
、ROLE_OWNER
等.
您可能最终让实体实现GrantedAuthority
,如下面的(伪代码)示例所示:
@Entity
class Role implements GrantedAuthority {
@Id
private String id;
@ManyToMany
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;
@ManyToMany
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
等.当用户通过身份验证时,请确保从UserDetails.getAuthority()方法返回其所有角色和相应操作的所有GrantedAuthority.
例子:
如果管理员登录生成的安全上下文将具有GrantedAuthority:
ROLE_ADMIN
、OP_DELETE_ACCOUNT
、OP_READ_ACCOUNT
、OP_RUN_BATCH_JOB
如果用户登录,它将具有:
UserDetailsService将负责收集所有角色和这些角色的所有操作,并通过返回的UserDetails实例中的getAuthority()方法使它们可用.