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.spring.security.interceptor;
020
021 import org.apache.shiro.authz.annotation.*;
022 import org.apache.shiro.mgt.SecurityManager;
023 import org.slf4j.Logger;
024 import org.slf4j.LoggerFactory;
025 import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
026 import org.springframework.core.annotation.AnnotationUtils;
027
028 import java.lang.annotation.Annotation;
029 import java.lang.reflect.Method;
030
031
032 /**
033 * TODO - complete JavaDoc
034 *
035 * @since 0.1
036 */
037 @SuppressWarnings({"unchecked"})
038 public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {
039
040 private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);
041
042 private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
043 new Class[] {
044 RequiresPermissions.class, RequiresRoles.class,
045 RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
046 };
047
048 protected SecurityManager securityManager = null;
049
050 /**
051 * Create a new AuthorizationAttributeSourceAdvisor.
052 */
053 public AuthorizationAttributeSourceAdvisor() {
054 setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
055 }
056
057 public SecurityManager getSecurityManager() {
058 return securityManager;
059 }
060
061 public void setSecurityManager(org.apache.shiro.mgt.SecurityManager securityManager) {
062 this.securityManager = securityManager;
063 }
064
065 /**
066 * Returns <tt>true</tt> if the method has any Shiro annotations, false otherwise.
067 * The annotations inspected are:
068 * <ul>
069 * <li>{@link org.apache.shiro.authz.annotation.RequiresAuthentication RequiresAuthentication}</li>
070 * <li>{@link org.apache.shiro.authz.annotation.RequiresUser RequiresUser}</li>
071 * <li>{@link org.apache.shiro.authz.annotation.RequiresGuest RequiresGuest}</li>
072 * <li>{@link org.apache.shiro.authz.annotation.RequiresRoles RequiresRoles}</li>
073 * <li>{@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions}</li>
074 * </ul>
075 *
076 * @param method the method to check for a Shiro annotation
077 * @param targetClass the class potentially declaring Shiro annotations
078 * @return <tt>true</tt> if the method has a Shiro annotation, false otherwise.
079 * @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, Class)
080 */
081 public boolean matches(Method method, Class targetClass) {
082 Method m = method;
083
084 if ( isAuthzAnnotationPresent(m) ) {
085 return true;
086 }
087
088 //The 'method' parameter could be from an interface that doesn't have the annotation.
089 //Check to see if the implementation has it.
090 if ( targetClass != null) {
091 try {
092 m = targetClass.getMethod(m.getName(), m.getParameterTypes());
093 if ( isAuthzAnnotationPresent(m) ) {
094 return true;
095 }
096 } catch (NoSuchMethodException ignored) {
097 //default return value is false. If we can't find the method, then obviously
098 //there is no annotation, so just use the default return value.
099 }
100 }
101
102 return false;
103 }
104
105 private boolean isAuthzAnnotationPresent(Method method) {
106 for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {
107 Annotation a = AnnotationUtils.findAnnotation(method, annClass);
108 if ( a != null ) {
109 return true;
110 }
111 }
112 return false;
113 }
114
115 }