View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.authz.aop;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  
24  import org.apache.shiro.aop.MethodInvocation;
25  import org.apache.shiro.authz.AuthorizationException;
26  
27  /**
28   * An <tt>AnnotationsAuthorizingMethodInterceptor</tt> is a MethodInterceptor that asserts a given method is authorized
29   * to execute based on one or more configured <tt>AuthorizingAnnotationMethodInterceptor</tt>s.
30   *
31   * <p>This allows multiple annotations on a method to be processed before the method
32   * executes, and if any of the <tt>AuthorizingAnnotationMethodInterceptor</tt>s indicate that the method should not be
33   * executed, an <tt>AuthorizationException</tt> will be thrown, otherwise the method will be invoked as expected.
34   *
35   * <p>It is essentially a convenience mechanism to allow multiple annotations to be processed in a single method
36   * interceptor.
37   *
38   * @since 0.2
39   */
40  public abstract class AnnotationsAuthorizingMethodInterceptor extends AuthorizingMethodInterceptor {
41  
42      /**
43       * The method interceptors to execute for the annotated method.
44       */
45      protected Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors;
46  
47      /**
48       * Default no-argument constructor that defaults the 
49       * {@link #methodInterceptors methodInterceptors} attribute to contain two interceptors by default - the
50       * {@link RoleAnnotationMethodInterceptor RoleAnnotationMethodInterceptor} and the
51       * {@link PermissionAnnotationMethodInterceptor PermissionAnnotationMethodInterceptor} to
52       * support role and permission annotations.
53       */
54      public AnnotationsAuthorizingMethodInterceptor() {
55          methodInterceptors = new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);
56          methodInterceptors.add(new RoleAnnotationMethodInterceptor());
57          methodInterceptors.add(new PermissionAnnotationMethodInterceptor());
58          methodInterceptors.add(new AuthenticatedAnnotationMethodInterceptor());
59          methodInterceptors.add(new UserAnnotationMethodInterceptor());
60          methodInterceptors.add(new GuestAnnotationMethodInterceptor());
61      }
62  
63      /**
64       * Returns the method interceptors to execute for the annotated method.
65       * <p/>
66       * Unless overridden by the {@link #setMethodInterceptors(java.util.Collection)} method, the default collection
67       * contains a
68       * {@link RoleAnnotationMethodInterceptor RoleAnnotationMethodInterceptor} and a
69       * {@link PermissionAnnotationMethodInterceptor PermissionAnnotationMethodInterceptor} to
70       * support role and permission annotations automatically.
71       * @return the method interceptors to execute for the annotated method.
72       */
73      public Collection<AuthorizingAnnotationMethodInterceptor> getMethodInterceptors() {
74          return methodInterceptors;
75      }
76  
77      /**
78       * Sets the method interceptors to execute for the annotated method.
79       * @param methodInterceptors the method interceptors to execute for the annotated method.
80       * @see #getMethodInterceptors()
81       */
82      public void setMethodInterceptors(Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors) {
83          this.methodInterceptors = methodInterceptors;
84      }
85  
86      /**
87       * Iterates over the internal {@link #getMethodInterceptors() methodInterceptors} collection, and for each one,
88       * ensures that if the interceptor
89       * {@link AuthorizingAnnotationMethodInterceptor#supports(org.apache.shiro.aop.MethodInvocation) supports}
90       * the invocation, that the interceptor
91       * {@link AuthorizingAnnotationMethodInterceptor#assertAuthorized(org.apache.shiro.aop.MethodInvocation) asserts}
92       * that the invocation is authorized to proceed.
93       */
94      protected void assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {
95          //default implementation just ensures no deny votes are cast:
96          Collection<AuthorizingAnnotationMethodInterceptor> aamis = getMethodInterceptors();
97          if (aamis != null && !aamis.isEmpty()) {
98              for (AuthorizingAnnotationMethodInterceptor aami : aamis) {
99                  if (aami.supports(methodInvocation)) {
100                     aami.assertAuthorized(methodInvocation);
101                 }
102             }
103         }
104     }
105 }