/** * Returns <tt>true</tt> if the method has any Shiro annotations, false otherwise. * The annotations inspected are: * <ul> * <li>{@link org.apache.shiro.authz.annotation.RequiresAuthentication RequiresAuthentication}</li> * <li>{@link org.apache.shiro.authz.annotation.RequiresUser RequiresUser}</li> * <li>{@link org.apache.shiro.authz.annotation.RequiresGuest RequiresGuest}</li> * <li>{@link org.apache.shiro.authz.annotation.RequiresRoles RequiresRoles}</li> * <li>{@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions}</li> * </ul> * * @param method the method to check for a Shiro annotation * @param targetClass the class potentially declaring Shiro annotations * @return <tt>true</tt> if the method has a Shiro annotation, false otherwise. * @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, Class) */ publicbooleanmatches(Method method, Class targetClass){ Method m = method;
if ( isAuthzAnnotationPresent(m) ) { returntrue; }
//The 'method' parameter could be from an interface that doesn't have the annotation. //Check to see if the implementation has it. if ( targetClass != null) { try { m = targetClass.getMethod(m.getName(), m.getParameterTypes()); if ( isAuthzAnnotationPresent(m) ) { returntrue; } } catch (NoSuchMethodException ignored) { //default return value is false. If we can't find the method, then obviously //there is no annotation, so just use the default return value. } }
returnfalse; }
privatebooleanisAuthzAnnotationPresent(Method method){ for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) { Annotation a = AnnotationUtils.findAnnotation(method, annClass); if ( a != null ) { returntrue; } } returnfalse; }
publicAopAllianceAnnotationsAuthorizingMethodInterceptor(){ List<AuthorizingAnnotationMethodInterceptor> interceptors = new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
//use a Spring-specific Annotation resolver - Spring's AnnotationUtils is nicer than the //raw JDK resolution process. 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 PermissionAnnotationMethodInterceptor(resolver)); interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver)); interceptors.add(new UserAnnotationMethodInterceptor(resolver)); interceptors.add(new GuestAnnotationMethodInterceptor(resolver));
/** * Iterates over the internal {@link #getMethodInterceptors() methodInterceptors} collection, and for each one, * ensures that if the interceptor * {@link AuthorizingAnnotationMethodInterceptor#supports(org.apache.shiro.aop.MethodInvocation) supports} * the invocation, that the interceptor * {@link AuthorizingAnnotationMethodInterceptor#assertAuthorized(org.apache.shiro.aop.MethodInvocation) asserts} * that the invocation is authorized to proceed. */ protectedvoidassertAuthorized(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.assertAuthorized(methodInvocation); } } } }
publicvoidassertAuthorized(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; } }
/** * Ensures that the calling <code>Subject</code> has the Annotation's specified permissions, and if not, throws an * <code>AuthorizingException</code> indicating access is denied. * * @param a the RequiresPermission annotation being inspected to check for one or more permissions * @throws org.apache.shiro.authz.AuthorizationException * if the calling <code>Subject</code> does not have the permission(s) necessary to * continue access or execution. */ publicvoidassertAuthorized(Annotation a)throws AuthorizationException { if (!(a instanceof RequiresPermissions)) return;
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]); } }
/* * @param principals the corresponding Subject's identifying principals with which to look up the Subject's * {@code AuthorizationInfo}. * @return the authorization information for the account associated with the specified {@code principals}, * or {@code null} if no account could be found. */ protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals){
if (principals == null) { returnnull; }
AuthorizationInfo info = null;
if (log.isTraceEnabled()) { log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]"); }
//查缓存,如果有AuthorizationInfo则返回 Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache(); if (cache != null) { if (log.isTraceEnabled()) { log.trace("Attempting to retrieve the AuthorizationInfo from cache."); } 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) { // Call template method if the info was not found in a cache info = doGetAuthorizationInfo(principals); // If the info is not null and the cache has been created, then cache the authorization info. if (info != null && cache != null) { if (log.isTraceEnabled()) { log.trace("Caching authorization info for principals: [" + principals + "]."); } Object key = getAuthorizationCacheKey(principals); cache.put(key, info); } }