首先在源码中找到了将权限字符串拆分的方法,如下:
//wildcardString 权限字符串
//caseSensitive 字符串大小写转换标记
protected void setParts(String wildcardString, boolean caseSensitive) {
//判断权限字符串不为空
if (wildcardString == null || wildcardString.trim().length() == 0) {
throw new IllegalArgumentException("Wildcard string cannot be null or empty. Make sure permission strings are properly formatted.");
}
wildcardString = wildcardString.trim();
//按照“:”切割字符串(PART_DIVIDER_TOKEN 为 ‘:’)
List<String> parts = CollectionUtils.asList(wildcardString.split(PART_DIVIDER_TOKEN));
this.parts = new ArrayList<Set<String>>();
//循环把切割后的字符串按照‘,’再次切割,然后放入权限集合中(SUBPART_DIVIDER_TOKEN 为 ‘,’)
for (String part : parts) {
Set<String> subparts = CollectionUtils.asSet(part.split(SUBPART_DIVIDER_TOKEN));
if (!caseSensitive) {
subparts = lowercase(subparts);
}
if (subparts.isEmpty()) {
throw new IllegalArgumentException("Wildcard string cannot contain parts with only dividers. Make sure permission strings are properly formatted.");
}
this.parts.add(subparts);
}
if (this.parts.isEmpty()) {
throw new IllegalArgumentException("Wildcard string cannot contain only dividers. Make sure permission strings are properly formatted.");
}
}
到此,shiro将权限字符串已经全部解析为单个权限字段如:
system:user,shopping:update,view -> (system) ((shopping)(user)) ((update)(view))
那么通配符在哪里匹配的呢?
下面这个方法是实现Permission接口的方法,检查是否拥有某个权限:
public boolean implies(Permission p) {
// By default only supports comparisons with other WildcardPermissions
if (!(p instanceof WildcardPermission)) {
return false;
}
//此处主要区分wp为外部传进来请求判断是否拥有的权限
WildcardPermission wp = (WildcardPermission) p;
List<Set<String>> otherParts = wp.getParts();
int i = 0;
for (Set<String> otherPart : otherParts) {
// If this permission has less parts than the other permission, everything after the number of parts contained
// in this permission is automatically implied, so return true
if (getParts().size() - 1 < i) {
//如果循环结束任然没有返回错误,那就是拥有这个权限,返回true
return true;
} else {
//part为系统内本身的权限列表
Set<String> part = getParts().get(i);
//如果内部不包含‘*’且没有这个权限的话,就认为没有权限
if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {
return false;
}
i++;
}
}
// If this permission has more parts than the other parts, only imply it if all of the other parts are wildcards
//这个for主要判断在内部权限字符串比外部传入的权限字符串长的情况,为防止user匹配到user:update(这样的匹配,假设只有update权限,如果有一个add操作,用user去匹配的话,匹配到update权限,通过的话,则代表add权限也拥有了,所以除非内部权限多出来的部分是*,否则都为失败)
for (; i < getParts().size(); i++) {
Set<String> part = getParts().get(i);
if (!part.contains(WILDCARD_TOKEN)) {
return false;
}
}
return true;
}
到此,我们知道了:
内部权限 | 外部权限 | 可否匹配 |
---|---|---|
system:user:upadate,view | system:user:* | 否 |
system:user:* | system:user:update | 是 |
system:user | system:user:update | 是 |
system:user:upadate,view | system:user | 否 |