用了shiro很长时间了,经常在controller的某个方法前加上注解: @RequiresPermissions("xx:xx"),就可以试用shiro的权限认证。
现在想研究下spring是如何调用这个过程的.
1、
public class AopAllianceAnnotationsAuthorizingMethodInterceptor
extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
return super.invoke(mi);//下一步
}
}
2、
public abstract class AuthorizingMethodInterceptor extends MethodInterceptorSupport {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
assertAuthorized(methodInvocation);//下一步
return methodInvocation.proceed();
}
}
注意:
public class AopAllianceAnnotationsAuthorizingMethodInterceptor
extends AnnotationsAuthorizingMethodInterceptor
extends AuthorizingMethodInterceptor
3、
public abstract class AnnotationsAuthorizingMethodInterceptor extends AuthorizingMethodInterceptor {
protected void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {
//default implementation just ensures no deny votes are cast:
Collection<AuthorizingAnnotationMethodInterceptor> aamis = getMethodInterceptors();
if (aamis != null && !aamis.isEmpty()) {
for (AuthorizingAnnotationMethodInterceptor aami : aamis) {
if (aami.supports(methodInvocation)) {
//当aami=PermissionAnnotationMethodInterceptor,下一步
aami.assertAuthorized(methodInvocation);
}
}
}
}
}
4、
public abstract class AuthorizingAnnotationMethodInterceptor extends AnnotationMethodInterceptor{
public void assertAuthorized(MethodInvocation mi) throws AuthorizationException {
try {
((AuthorizingAnnotationHandler)getHandler()).assertAuthorized(getAnnotation(mi));//下一步
}
catch(AuthorizationException ae) {
// Annotation handler doesn't know why it was called, so add the information here if possible.
// Don't wrap the exception here since we don't want to mask the specific exception, such as
// UnauthenticatedException etc.
if (ae.getCause() == null) ae.initCause(new AuthorizationException("Not authorized to invoke method: " + mi.getMethod()));
throw ae;
}
}
}
5、
public class PermissionAnnotationHandler extends AuthorizingAnnotationHandler {
public void assertAuthorized(Annotation a) throws AuthorizationException {
if (!(a instanceof RequiresPermissions)) return;
RequiresPermissions rpAnnotation = (RequiresPermissions) a;
String[] perms = getAnnotationValue(a);
Subject subject = getSubject();
if (perms.length == 1) {
subject.checkPermission(perms[0]);//下一步
return;
}
if (Logical.AND.equals(rpAnnotation.logical())) {
getSubject().checkPermissions(perms);
return;
}
if (Logical.OR.equals(rpAnnotation.logical())) {
// Avoid processing exceptions unnecessarily - "delay" throwing the exception by calling hasRole first
boolean hasAtLeastOnePermission = false;
for (String permission : perms) if (getSubject().isPermitted(permission)) hasAtLeastOnePermission = true;
// Cause the exception if none of the role match, note that the exception message will be a bit misleading
if (!hasAtLeastOnePermission) getSubject().checkPermission(perms[0]);
}
}
}
6、
public class DelegatingSubject implements Subject {
public void checkPermission(String permission) throws AuthorizationException {
assertAuthzCheckPossible();
securityManager.checkPermission(getPrincipals(), permission);//下一步
}
}
7、
public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager {
public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {
this.authorizer.checkPermission(principals, permission);//下一步
}
}
8、
public class ModularRealmAuthorizer implements Authorizer, PermissionResolverAware, RolePermissionResolverAware {
public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {
assertRealmsConfigured();
//isPermitted(principals, permission)下一步
if (!isPermitted(principals, permission)) {
throw new UnauthorizedException("Subject does not have permission [" + permission + "]");
}
}
public boolean isPermitted(PrincipalCollection principals, String permission) {
assertRealmsConfigured();
for (Realm realm : getRealms()) {
if (!(realm instanceof Authorizer)) continue;
//isPermitted(principals, permission)下一步
if (((Authorizer) realm).isPermitted(principals, permission)) {
return true;
}
}
return false;
}
}
9、
public abstract class AuthorizingRealm extends AuthenticatingRealm
implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
public boolean isPermitted(PrincipalCollection principals, String permission) {
Permission p = getPermissionResolver().resolvePermission(permission);
return isPermitted(principals, p);//下一步
}
public boolean isPermitted(PrincipalCollection principals, Permission permission) {
AuthorizationInfo info = getAuthorizationInfo(principals);
return isPermitted(permission, info);//下一步
}
//最终的方法。如果能找到相应的权限标记,则返回true.
protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
Collection<Permission> perms = getPermissions(info);
if (perms != null && !perms.isEmpty()) {
for (Permission perm : perms) {
// public boolean implies(Permission p)方法的比较稍微复杂,就不贴出来了。
// 知道在里面进行最终的权限验证,找到就返回true.
if (perm.implies(permission)) {
return true;
}
}
}
return false;
}
}