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.spring.security.interceptor;
20
21 import org.apache.shiro.authz.annotation.*;
22 import org.apache.shiro.mgt.SecurityManager;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
26 import org.springframework.core.annotation.AnnotationUtils;
27
28 import java.lang.annotation.Annotation;
29 import java.lang.reflect.Method;
30
31
32 /**
33 * TODO - complete JavaDoc
34 *
35 * @since 0.1
36 */
37 @SuppressWarnings({"unchecked"})
38 public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {
39
40 private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);
41
42 private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
43 new Class[] {
44 RequiresPermissions.class, RequiresRoles.class,
45 RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
46 };
47
48 protected SecurityManager securityManager = null;
49
50 /**
51 * Create a new AuthorizationAttributeSourceAdvisor.
52 */
53 public AuthorizationAttributeSourceAdvisor() {
54 setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
55 }
56
57 public SecurityManager getSecurityManager() {
58 return securityManager;
59 }
60
61 public void setSecurityManager(org.apache.shiro.mgt.SecurityManager securityManager) {
62 this.securityManager = securityManager;
63 }
64
65 /**
66 * Returns <tt>true</tt> if the method or the class has any Shiro annotations, false otherwise.
67 * The annotations inspected are:
68 * <ul>
69 * <li>{@link org.apache.shiro.authz.annotation.RequiresAuthentication RequiresAuthentication}</li>
70 * <li>{@link org.apache.shiro.authz.annotation.RequiresUser RequiresUser}</li>
71 * <li>{@link org.apache.shiro.authz.annotation.RequiresGuest RequiresGuest}</li>
72 * <li>{@link org.apache.shiro.authz.annotation.RequiresRoles RequiresRoles}</li>
73 * <li>{@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions}</li>
74 * </ul>
75 *
76 * @param method the method to check for a Shiro annotation
77 * @param targetClass the class potentially declaring Shiro annotations
78 * @return <tt>true</tt> if the method has a Shiro annotation, false otherwise.
79 * @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, Class)
80 */
81 public boolean matches(Method method, Class targetClass) {
82 Method m = method;
83
84 if ( isAuthzAnnotationPresent(m) ) {
85 return true;
86 }
87
88 //The 'method' parameter could be from an interface that doesn't have the annotation.
89 //Check to see if the implementation has it.
90 if ( targetClass != null) {
91 try {
92 m = targetClass.getMethod(m.getName(), m.getParameterTypes());
93 return isAuthzAnnotationPresent(m) || isAuthzAnnotationPresent(targetClass);
94 } catch (NoSuchMethodException ignored) {
95 //default return value is false. If we can't find the method, then obviously
96 //there is no annotation, so just use the default return value.
97 }
98 }
99
100 return false;
101 }
102
103 private boolean isAuthzAnnotationPresent(Class<?> targetClazz) {
104 for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {
105 Annotation a = AnnotationUtils.findAnnotation(targetClazz, annClass);
106 if ( a != null ) {
107 return true;
108 }
109 }
110 return false;
111 }
112
113 private boolean isAuthzAnnotationPresent(Method method) {
114 for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {
115 Annotation a = AnnotationUtils.findAnnotation(method, annClass);
116 if ( a != null ) {
117 return true;
118 }
119 }
120 return false;
121 }
122
123 }