shiro授权源码
在spring配置文件中开启shiro注解
- <!-- 开启shiro注解支持-->
- <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
- <property name="securityManager" ref="securityManager"/>
- </bean>
uthorizationAttributeSourceAdvisor类继承了StaticMethodMatcherPointcutAdvisor类,是spring AOP的一种方式
- public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {
- private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);
- private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
- new Class[] {
- RequiresPermissions.class, RequiresRoles.class,
- RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
- };
- protected SecurityManager securityManager = null;
- /**
- * Create a new AuthorizationAttributeSourceAdvisor.
- */
- public AuthorizationAttributeSourceAdvisor() {
- setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
- }
初始化构造函数事调用setAdvice,参数传入了匿名内部类(AopAllianceAnnotationsAuthorizingMethodInterceptor)
- public AopAllianceAnnotationsAuthorizingMethodInterceptor() {
- List<AuthorizingAnnotationMethodInterceptor> interceptors =
- new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
- AnnotationResolver resolver = new SpringAnnotationResolver();
- //we can re-use the same resolver instance - it does not retain state:
- interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
- interceptors.add(new PermissionAnnotationMethodInterceptorresolver));
interceptors集合中添加PermissionAnnotationMethodInterceptor
- public PermissionAnnotationMethodInterceptor(AnnotationResolver resolver) {
- super( new PermissionAnnotationHandler(), resolver);
- }
调用父类AuthorizingAnnotationMethodInterceptor的构造方法,传了了权限注解处理类、注解解析器,看父类中AOP执行的方法invoke()
- public Object invoke(MethodInvocation methodInvocation) throws Throwable {
- assertAuthorized(methodInvocation);
- return methodInvocation.proceed();
- }
invoke()方法中调用assertAuthorized()方法
- 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;
- }
- }
其中((AuthorizingAnnotationHandler)getHandler()).assertAuthorized(getAnnotation(mi)),这行代码实际就是调用之前传入的注解处理类中的assertAuthorized方法
查看PermissionAnnotationHandler的对应方法
- 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]);
- }
- }
方法中调用subject.checkPermission(),实际调用实现类DelegatingSubject.checkPermission()
- public void checkPermission(String permission) throws AuthorizationException {
- assertAuthzCheckPossible();
- securityManager.checkPermission(getPrincipals(), permission);
- }
assertAuthzCheckPossible()
securityManager.checkPermission(),实际调用ModularRealmAuthorizer的checkPermission()
- public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {
- assertRealmsConfigured();
- if (!isPermitted(principals, permission)) {
- throw new UnauthorizedException("Subject does not have permission [" + permission + "]");
- }
- }
assertRealmsConfigured()
isPermitted()
- 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;
- }
接着调用authorizingRealm中的isPermitted()
- public boolean isPermitted(PrincipalCollection principals, Permission permission) {
- AuthorizationInfo info = getAuthorizationInfo(principals);
- return isPermitted(permission, info);
- }
getAuthorizationInfo(),先从缓存中获取AuthorizationInfo,没有就从自定以realm中的doGetAuthorizationInfo()中获取
- protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
- ...
- AuthorizationInfo info = null;
- ...
- Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
- if (cache != null) {
- ...
- Object key = getAuthorizationCacheKey(principals);
- info = cache.get(key);
- if (log.isTraceEnabled()) {
- if (info == null) {
- log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
- } else {
- log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
- }
- }
- }
- if (info == null) {
- info = doGetAuthorizationInfo(principals);
- ...
- }
- return info;
- }
返回AuthorizationInfo后调用isPermitted()比较权限字符串是否包含权限注解中的字符串
- 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;
- }
通过AuthorizationInfo获取对应的权限集合
接着调用wildCardPermission中的方法implies()
校验失败抛出UnauthorizedException异常
ModularRealmAuthorizer中的checkPermission()
- public void checkPermission(PrincipalCollection principals, String permission) throws AuthorizationException {
- assertRealmsConfigured();
- if (!isPermitted(principals, permission)) {
- throw new UnauthorizedException("Subject does not have permission [" + permission + "]");
- }
- }