RequiresPermissions的作用
RequiresPermissions是shiro提供的一个注解类。主要是用作权限校验的一种方式。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissions {
/**
* The permission string which will be passed to {@link org.apache.shiro.subject.Subject#isPermitted(String)}
* to determine if the user is allowed to invoke the code protected by this annotation.
*/
String[] value();
/**
* The logical operation for the permission checks in case multiple roles are specified. AND is the default
* @since 1.1.0
*/
Logical logical() default Logical.AND;
}
一般情况下,注解类作用在需要拦截的方法上。
从value的注释上可以看到,注解上的第一个参数的值会传到Subject的isPermitted方法去。所以原理都是通过Subject的isPermitted去校验权限。
RequiresPermissions的value格式
- 简单形式
value只是一个普通的字符串比如:@RequiresPermissions(“dosomething”) - 多层级形式
用冒号隔开两个字符串,比如:@RequiresPermissions(“dosomething:view,edit”)
冒号隔开的第一个字符串一般是操作的领域对象,而第二个字符串一般是操作的类型。 - 实例级访问控制
用冒号隔开多个字符串,比如:@RequiresPermissions(“dosomething:view,edit:213”)冒号隔开的第三个字符串内容一般是一个操作对象的id,来控制具体的对象实例是否有权限来调用方法。
这个格式应该只是一种规范标准,不一定非要严格执行才能达到效果。
# WildcardPermissionResolver类中
public Permission resolvePermission(String permissionString) {
return new WildcardPermission(permissionString);
}
#AuthorizingRealm类中的两个方法:
根据字符串resolve成的一个Permission
public boolean isPermitted(PrincipalCollection principals, String permission) {
Permission p = getPermissionResolver().resolvePermission(permission);//实现在WildcardPermissionResolver类中
return isPermitted(principals, p);
}
在AuthorizingRealm类中的权限比较实现。而其中的permission就是上面生成的,而AuthorizationInfo的内容一般都是从数据库等等地方查询出权限列表寄放到info里。
//visibility changed from private to protected per SHIRO-332
protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
Collection<Permission> perms = getPermissions(info);
if (perms != null && !perms.isEmpty()) {
for (Permission perm : perms) {
if (perm.implies(permission)) {
return true;
}
}
}
return false;
}
public boolean implies(Permission p) {
// By default only supports comparisons with other WildcardPermissions
if (!(p instanceof WildcardPermission)) {
return false;
}
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) {
return true;
} else {
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 (; i < getParts().size(); i++) {
Set<String> part = getParts().get(i);
if (!part.contains(WILDCARD_TOKEN)) {
return false;
}
}
return true;
}
所以value只要和存储在数据库里面的权限信息段一致应该就可以。