最近在整理知识点的时候,对于SpringSecurity中的那个ROLE_
真的感觉很奇怪,今天查了不少,找到一点点东西,可以丰富一些杂识哈。😁
喜欢的话,一起坚持啦!!!
一、前言:
先讲一下我的好奇点:
最近在使用Security做安全权限控制,可以看到下图,这个方法可以通过的角色是USER
,但是我的表中的数据是这样的。
我就对于这个前缀ROLE_
非常的好奇。(因为是许久之前的代码了,就忘记的差不多啦🐕狗头保命)
我做过测试如果使用@PreAuthorize("hasAnyRole('USER')")
此注解的话:总之得拼出ROLE_USER
- 数据库上的那个权限or角色的字段必须为
ROLE_USER
,
- 又或者啊数据库写成
USER
,但是在使用注解时写成这样也可以@PreAuthorize("hasAnyRole('ROLE_USER')")
。
我测试访问是可以通过的,这样我就对于为什么一定要这样,就更好奇,所以就开始了属于我的好奇之旅哈。😂
二、目前所知
看完查到的博客,暂时还没有找到security的设计者这样设计的原因,但是对于为什么要这么去写,在源码中有所提及:
/** 投票是否有任何ConfigAttribute.getAttribute()以前缀开头,表明它是一个角色。 默认前缀字符串是ROLE_ , 但这可以覆盖为任何值。 它也可以设置为空,这意味着基本上任何属性都将被投票。 如下文进一步描述的,空前缀的效果可能不是很理想。 如果没有配置属性以角色前缀开头,则弃权。 如果存在与以角色前缀开头的ConfigAttribute完全匹配的GrantedAuthority ,则投票授予访问权限。 如果没有与以角色前缀开头的ConfigAttribute完全匹配的GrantedAuthority ,则投票拒绝访问。 空的角色前缀意味着投票者将为每个 ConfigAttribute 投票。 当使用不同类别的 ConfigAttributes 时,这将不是最佳的,因为投票者将为不代表角色的属性投票。 但是,当使用没有前缀的预先存在的角色名称时,此选项可能会有一些用处,并且无法在读取它们时使用角色前缀作为前缀, 例如在org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl 。 所有比较和前缀都区分大小写。 */ public class RoleVoter implements AccessDecisionVoter<Object> { private String rolePrefix = "ROLE_"; public String getRolePrefix() { return rolePrefix; } public void setRolePrefix(String rolePrefix) {this.rolePrefix = rolePrefix; } // 这里就是判断是否符合 public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) { return true; } else { return false; } } public boolean supports(Class<?> clazz) { return true; } //判断是否授予访问权限。 public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { if (authentication == null) { return ACCESS_DENIED; } int result = ACCESS_ABSTAIN; Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication); for (ConfigAttribute attribute : attributes) { if (this.supports(attribute)) { result = ACCESS_DENIED; // Attempt to find a matching granted authority for (GrantedAuthority authority : authorities) { if (attribute.getAttribute().equals(authority.getAuthority())) { return ACCESS_GRANTED; } } } } return result; } Collection<? extends GrantedAuthority> extractAuthorities( Authentication authentication) { return authentication.getAuthorities(); } }
有以下几个点:
ROLE_
是默认的一个前缀,可以覆盖,但是不建议为空,这点我在👉官方文档中也查询到了。因为如果为空的话,空的角色前缀意味着投票者将为每个 ConfigAttribute 投票。就是每个都可以通过的意思(自我理解)。
- 但是如果没有配置前缀的话,那么就会直接判定为权限不足,继而不通过。
- 只有以角色前缀开头ConfigAttribute完全匹配的GrantedAuthority(表示授予Authentication对象的权限) 的才能被授权访问。
就是权限名是完全一样才能被访问,否则就被拒绝。
三、自言自语
学习必须的带上兴趣,才能变得不一样,有动力,有冲劲。😁
感兴趣的话,大家可以再试着Debug、bug、bug一下下哦。