shiro授权代码流程

授权流程

  1. shiro拦截到需要权限的url的时候,就传入需要的permission,进行subject.isPermitted(permission)的检查。
  2. DelegatingSubject代理类接收到permission后,调用自己的isPermitted方法进行判断。判断分为两步:hasPrincipals && securityManager.isPermitted(getPrincipals(),permission)。首先是判断用户的身份信息是否存在切有效,第二步是判断用户的凭证信息和用户所要请求的权限是否符合。
  3. AuthorizingSecurityManager调用this.authorizer.isPermitted(principals,permission)进行判断,返回一个布尔值。authorizer在AuthorizingSecurityManager的构造函数中就被new,就是ModularRealmAuthorizer。
  4. ModularRealmAuthorizer接收到参数后,遍历realm,进行权限判断。((Authorizer) realm).isPermitted(principals, permission)。
  5. 上面的isPermitted方法是定义在AuthorizingRealm中的,自定义的realm都要继承这个类,也就是说自定义的realm都有这个判断的方法。realm内部首先会拿着principals去获取到用户的权限信息AuthorizationInfo,然后对权限信息进行遍历查找,看看permission是否存在于info中,如果存在就返回true。

AuthorizationTest

传入权限标识符,返回一个布尔值,表示是否有这个权限。

1
2
// isPermitted里面传入的是权限标识符
subject.isPermitted("user:create:1");

DelegatingSubject

权限标识符传入后,进行两个判断,一个是当前是否存在这个身份信息,另外一个是这个用户是否有这个权限,两个都是true才返回true,权限认证通过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// String类型的权限标识符
public boolean isPermitted(String permission) {
return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
}
// 权限
public boolean isPermitted(Permission permission) {
return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
}
// 是否有用户凭证信息,也就是用户是否存在的意思
protected boolean hasPrincipals() {
return !CollectionUtils.isEmpty(getPrincipals());
}
// 返回主身份信息吗?只返回了集合中的第一个
public PrincipalCollection getPrincipals() {
List<PrincipalCollection> runAsPrincipals = getRunAsPrincipalsStack();
return CollectionUtils.isEmpty(runAsPrincipals) ? this.principals : runAsPrincipals.get(0);
}
// 从session中获取用户的身份凭证信息
@SuppressWarnings("unchecked")
private List<PrincipalCollection> getRunAsPrincipalsStack() {
Session session = getSession(false);
if (session != null) {
return (List<PrincipalCollection>) session.getAttribute(RUN_AS_PRINCIPALS_SESSION_KEY);
}
return null;
}

AuthorizingSecurityManager

调用ModularRealmAuthorizer中的权限判断方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private Authorizer authorizer;
// 构造函数中就new了一个ModularRealmAuthorizer
public AuthorizingSecurityManager() {
super();
this.authorizer = new ModularRealmAuthorizer();
}
public boolean isPermitted(PrincipalCollection principals, String permissionString) {
return this.authorizer.isPermitted(principals, permissionString);
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
return this.authorizer.isPermitted(principals, permission);
}

ModularRealmAuthorizer

遍历realm集合,只要有一个realm判断认证通过,就返回true,这边的realm可以是自己设置进去的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public boolean isPermitted(PrincipalCollection principals, String permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
if (((Authorizer) realm).isPermitted(principals, permission)) {
return true;
}
}
return false;
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
// 调用realm来进行授权的查询,只要一个满足就返回true
if (((Authorizer) realm).isPermitted(principals, permission)) {
return true;
}
}
return false;
}

AuthorizingRealm

这是realm内部进行权限查询的流程,要求的自定义的realm全部都要继承它。会把用户的身份信息传入进去,然后获取到用户的授权信息,AuthorizerInfo,然后遍历info中的权限信息,只要存在,就返回true。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public boolean isPermitted(PrincipalCollection principals, String permission) {
Permission p = getPermissionResolver().resolvePermission(permission);
return isPermitted(principals, p);
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
// 这就是在自定义的realm里override的方法
AuthorizationInfo info = getAuthorizationInfo(principals);
// 会从info中获取信息
return isPermitted(permission, info);
}
private 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;
}