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 */ 019package org.apache.shiro.authz.aop; 020 021import org.apache.shiro.aop.AnnotationMethodInterceptor; 022import org.apache.shiro.aop.AnnotationResolver; 023import org.apache.shiro.aop.MethodInvocation; 024import org.apache.shiro.authz.AuthorizationException; 025 026 027/** 028 * An <tt>AnnotationMethodInterceptor</tt> that asserts the calling code is authorized to execute the method 029 * before allowing the invocation to continue by inspecting code annotations to perform an access control check. 030 * 031 * @since 0.1 032 */ 033public abstract class AuthorizingAnnotationMethodInterceptor extends AnnotationMethodInterceptor { 034 035 /** 036 * Constructor that ensures the internal <code>handler</code> is set which will be used to perform the 037 * authorization assertion checks when a supported annotation is encountered. 038 * 039 * @param handler the internal <code>handler</code> used to perform authorization assertion checks when a 040 * supported annotation is encountered. 041 */ 042 public AuthorizingAnnotationMethodInterceptor(AuthorizingAnnotationHandler handler) { 043 super(handler); 044 } 045 046 /** 047 * @param handler 048 * @param resolver 049 * @since 1.1 050 */ 051 public AuthorizingAnnotationMethodInterceptor(AuthorizingAnnotationHandler handler, 052 AnnotationResolver resolver) { 053 super(handler, resolver); 054 } 055 056 /** 057 * Ensures the <code>methodInvocation</code> is allowed to execute first before proceeding by calling the 058 * {@link #assertAuthorized(org.apache.shiro.aop.MethodInvocation) assertAuthorized} method first. 059 * 060 * @param methodInvocation the method invocation to check for authorization prior to allowing it to proceed/execute. 061 * @return the return value from the method invocation 062 * (the value of {@link org.apache.shiro.aop.MethodInvocation#proceed() MethodInvocation.proceed()}). 063 * @throws org.apache.shiro.authz.AuthorizationException if the <code>MethodInvocation</code> is not allowed to proceed. 064 * @throws Throwable if any other error occurs. 065 */ 066 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 067 assertAuthorized(methodInvocation); 068 return methodInvocation.proceed(); 069 } 070 071 /** 072 * Ensures the calling Subject is authorized to execute the specified <code>MethodInvocation</code>. 073 * <p/> 074 * As this is an AnnotationMethodInterceptor, this implementation merely delegates to the internal 075 * {@link AuthorizingAnnotationHandler AuthorizingAnnotationHandler} by first acquiring the annotation by 076 * calling {@link #getAnnotation(MethodInvocation) getAnnotation(methodInvocation)} and then calls 077 * {@link AuthorizingAnnotationHandler#assertAuthorized(java.lang.annotation.Annotation) 078 * handler.assertAuthorized(annotation)}. 079 * 080 * @param mi the <code>MethodInvocation</code> to check to see if it is allowed to proceed/execute. 081 * @throws AuthorizationException if the method invocation is not allowed to continue/execute. 082 */ 083 public void assertAuthorized(MethodInvocation mi) throws AuthorizationException { 084 try { 085 ((AuthorizingAnnotationHandler) getHandler()).assertAuthorized(getAnnotation(mi)); 086 } catch (AuthorizationException ae) { 087 // Annotation handler doesn't know why it was called, so add the information here if possible. 088 // Don't wrap the exception here since we don't want to mask the specific exception, such as 089 // UnauthenticatedException etc. 090 if (ae.getCause() == null) { 091 ae.initCause(new AuthorizationException("Not authorized to invoke method: " + mi.getMethod())); 092 } 093 throw ae; 094 } 095 } 096}