001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.authz.aop;
020
021 import java.util.ArrayList;
022 import java.util.Collection;
023
024 import org.apache.shiro.aop.MethodInvocation;
025 import org.apache.shiro.authz.AuthorizationException;
026
027 /**
028 * An <tt>AnnotationsAuthorizingMethodInterceptor</tt> is a MethodInterceptor that asserts a given method is authorized
029 * to execute based on one or more configured <tt>AuthorizingAnnotationMethodInterceptor</tt>s.
030 *
031 * <p>This allows multiple annotations on a method to be processed before the method
032 * executes, and if any of the <tt>AuthorizingAnnotationMethodInterceptor</tt>s indicate that the method should not be
033 * executed, an <tt>AuthorizationException</tt> will be thrown, otherwise the method will be invoked as expected.
034 *
035 * <p>It is essentially a convenience mechanism to allow multiple annotations to be processed in a single method
036 * interceptor.
037 *
038 * @author Les Hazlewood
039 * @since 0.2
040 */
041 public abstract class AnnotationsAuthorizingMethodInterceptor extends AuthorizingMethodInterceptor {
042
043 /**
044 * The method interceptors to execute for the annotated method.
045 */
046 protected Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors;
047
048 /**
049 * Default no-argument constructor that defaults the
050 * {@link #methodInterceptors methodInterceptors} attribute to contain two interceptors by default - the
051 * {@link RoleAnnotationMethodInterceptor RoleAnnotationMethodInterceptor} and the
052 * {@link PermissionAnnotationMethodInterceptor PermissionAnnotationMethodInterceptor} to
053 * support role and permission annotations.
054 */
055 public AnnotationsAuthorizingMethodInterceptor() {
056 methodInterceptors = new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
057 methodInterceptors.add(new RoleAnnotationMethodInterceptor());
058 methodInterceptors.add(new PermissionAnnotationMethodInterceptor());
059 methodInterceptors.add(new AuthenticatedAnnotationMethodInterceptor());
060 methodInterceptors.add(new UserAnnotationMethodInterceptor());
061 methodInterceptors.add(new GuestAnnotationMethodInterceptor());
062 }
063
064 /**
065 * Returns the method interceptors to execute for the annotated method.
066 * <p/>
067 * Unless overridden by the {@link #setMethodInterceptors(java.util.Collection)} method, the default collection
068 * contains a
069 * {@link RoleAnnotationMethodInterceptor RoleAnnotationMethodInterceptor} and a
070 * {@link PermissionAnnotationMethodInterceptor PermissionAnnotationMethodInterceptor} to
071 * support role and permission annotations automatically.
072 * @return the method interceptors to execute for the annotated method.
073 */
074 public Collection<AuthorizingAnnotationMethodInterceptor> getMethodInterceptors() {
075 return methodInterceptors;
076 }
077
078 /**
079 * Sets the method interceptors to execute for the annotated method.
080 * @param methodInterceptors the method interceptors to execute for the annotated method.
081 * @see #getMethodInterceptors()
082 */
083 public void setMethodInterceptors(Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors) {
084 this.methodInterceptors = methodInterceptors;
085 }
086
087 /**
088 * Iterates over the internal {@link #getMethodInterceptors() methodInterceptors} collection, and for each one,
089 * ensures that if the interceptor
090 * {@link AuthorizingAnnotationMethodInterceptor#supports(org.apache.shiro.aop.MethodInvocation) supports}
091 * the invocation, that the interceptor
092 * {@link AuthorizingAnnotationMethodInterceptor#assertAuthorized(org.apache.shiro.aop.MethodInvocation) asserts}
093 * that the invocation is authorized to proceed.
094 */
095 protected void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {
096 //default implementation just ensures no deny votes are cast:
097 Collection<AuthorizingAnnotationMethodInterceptor> aamis = getMethodInterceptors();
098 if (aamis != null && !aamis.isEmpty()) {
099 for (AuthorizingAnnotationMethodInterceptor aami : aamis) {
100 if (aami.supports(methodInvocation)) {
101 aami.assertAuthorized(methodInvocation);
102 }
103 }
104 }
105 }
106 }