您的位置:首页 > 其它

自定义权限注解

2016-01-05 15:48 323 查看
1、Shiro权限原理:spring-shiro.xml需要配置
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
</bean>这个bean,用来匹配他自己定义的权限注解
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shiro.spring.security.interceptor;

import org.apache.shiro.authz.annotation.*;
import org.apache.shiro.mgt.SecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
* TODO - complete JavaDoc
*
* @since 0.1
*/
@SuppressWarnings({"unchecked"})
public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {

private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);

private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =
new Class[] {
RequiresPermissions.class, RequiresRoles.class,
RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class
};

protected SecurityManager securityManager = null;

/**
* Create a new AuthorizationAttributeSourceAdvisor.
*/
public AuthorizationAttributeSourceAdvisor() {
setAdvice(new AopAllianceAnnotationsAuthorizingMethodInterceptor());
}

public SecurityManager getSecurityManager() {
return securityManager;
}

public void setSecurityManager(org.apache.shiro.mgt.SecurityManager securityManager) {
this.securityManager = securityManager;
}

/**
* Returns <tt>true</tt> if the method has any Shiro annotations, false otherwise.
* The annotations inspected are:
* <ul>
* <li>{@link org.apache.shiro.authz.annotation.RequiresAuthentication RequiresAuthentication}</li>
* <li>{@link org.apache.shiro.authz.annotation.RequiresUser RequiresUser}</li>
* <li>{@link org.apache.shiro.authz.annotation.RequiresGuest RequiresGuest}</li>
 
3ff0
; * <li>{@link org.apache.shiro.authz.annotation.RequiresRoles RequiresRoles}</li>
* <li>{@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions}</li>
* </ul>
*
* @param method the method to check for a Shiro annotation
* @param targetClass the class potentially declaring Shiro annotations
* @return <tt>true</tt> if the method has a Shiro annotation, false otherwise.
* @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, Class)
*/
public boolean matches(Method method, Class targetClass) {
Method m = method;

if ( isAuthzAnnotationPresent(m) ) {
return true;
}

//The 'method' parameter could be from an interface that doesn't have the annotation.
//Check to see if the implementation has it.
if ( targetClass != null) {
try {
m = targetClass.getMethod(m.getName(), m.getParameterTypes());
if ( isAuthzAnnotationPresent(m) ) {
return true;
}
} catch (NoSuchMethodException ignored) {
//default return value is false. If we can't find the method, then obviously
//there is no annotation, so just use the default return value.
}
}

return false;
}

private boolean isAuthzAnnotationPresent(Method method) {
for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {
Annotation a = AnnotationUtils.findAnnotation(method, annClass);
if ( a != null ) {
return true;
}
}
return false;
}

}
此类继承StaticMethodMatcherPointcutAdvisor父类, AUTHZ_ANNOTATION_CLASSES 是他自己定义的注解类集合,matches方法匹配访问方法是否有他自己定义的注解。AopAllianceAnnotationsAuthorizingMethodInterceptor这个类是拦截器的总类

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0 *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.shiro.spring.security.interceptor;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.shiro.aop.AnnotationResolver;
import org.apache.shiro.authz.aop.*;
import org.apache.shiro.spring.aop.SpringAnnotationResolver;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
* Allows Shiro Annotations to work in any <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a>
* specific implementation environment (for example, Spring).
*
* @since 0.2
*/
public class AopAllianceAnnotationsAuthorizingMethodInterceptor
extends AnnotationsAuthorizingMethodInterceptor implements MethodInterceptor {

public AopAllianceAnnotationsAuthorizingMethodInterceptor() {
List<AuthorizingAnnotationMethodInterceptor> interceptors =
new ArrayList<AuthorizingAnnotationMethodInterceptor>(5);

//use a Spring-specific Annotation resolver - Spring's AnnotationUtils is nicer than the
//raw JDK resolution process.
AnnotationResolver resolver = new SpringAnnotationResolver();
//we can re-use the same resolver instance - it does not retain state:
interceptors.add(new RoleAnnotationMethodInterceptor(resolver));
interceptors.add(new PermissionAnnotationMethodInterceptor(resolver));
interceptors.add(new AuthenticatedAnnotationMethodInterceptor(resolver));
interceptors.add(new UserAnnotationMethodInterceptor(resolver));
interceptors.add(new GuestAnnotationMethodInterceptor(resolver));

setMethodInterceptors(interceptors);
}
/**
* Creates a {@link MethodInvocation MethodInvocation} that wraps an
* {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} instance,
* enabling Shiro Annotations in <a href="http://aopalliance.sourceforge.net/">AOP Alliance</a> environments
* (Spring, etc).
*
* @param implSpecificMethodInvocation AOP Alliance {@link org.aopalliance.intercept.MethodInvocation MethodInvocation}
* @return a Shiro {@link MethodInvocation MethodInvocation} instance that wraps the AOP Alliance instance.
*/
protected org.apache.shiro.aop.MethodInvocation createMethodInvocation(Object implSpecificMethodInvocation) {
final MethodInvocation mi = (MethodInvocation) implSpecificMethodInvocation;

return new org.apache.shiro.aop.MethodInvocation() {
public Method getMethod() {
return mi.getMethod();
}

public Object[] getArguments() {
return mi.getArguments();
}

public String toString() {
return "Method invocation [" + mi.getMethod() + "]";
}

public Object proceed() throws Throwable {
return mi.proceed();
}

public Object getThis() {
return mi.getThis();
}
};
}

/**
* Simply casts the method argument to an
* {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation} and then
* calls <code>methodInvocation.{@link org.aopalliance.intercept.MethodInvocation#proceed proceed}()</code>
*
* @param aopAllianceMethodInvocation the {@link org.aopalliance.intercept.MethodInvocation org.aopalliance.intercept.MethodInvocation}
* @return the {@link org.aopalliance.intercept.MethodInvocation#proceed() org.aopalliance.intercept.MethodInvocation.proceed()} method call result.
* @throws Throwable if the underlying AOP Alliance <code>proceed()</code> call throws a <code>Throwable</code>.
*/
protected Object continueInvocation(Object aopAllianceMethodInvocation) throws Throwable {
MethodInvocation mi = (MethodInvocation) aopAllianceMethodInvocation;
return mi.proceed();
}

/**
* Creates a Shiro {@link MethodInvocation MethodInvocation} instance and then immediately calls
* {@link org.apache.shiro.authz.aop.AuthorizingMethodInterceptor#invoke super.invoke}.
*
* @param methodInvocation the AOP Alliance-specific <code>methodInvocation</code> instance.
* @return the return value from invoking the method invocation.
* @throws Throwable if the underlying AOP Alliance method invocation throws a <code>Throwable</code>.
*/
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
org.apache.shiro.aop.MethodInvocation mi = createMethodInvocation(methodInvocation);
return super.invoke(mi);
}
}

这个类是申明的AopAllianceAnnotationsAuthorizingMethodInterceptor拦截器的集合,需要注意的是他的每一个拦截器 如RoleAnnotationMethodInterceptor:主要由一个XXHandler(匹配注解值和用户权限)和AnnotationResolver(获取注解对象)构成。

2、仿写:bean类继承org.springframework.aop.support.StaticMethodMatcherPointcutAdviso
r这个类,通过实现match方法匹配切点,实例所示
public class AuthorizationAdvisor extends StaticMethodMatcherPointcutAdvisor{

/**

* @Fields serialVersionUID : TODO

*/

private static final long serialVersionUID = -880533033433547002L;

private static final Logger log = LoggerFactory.getLogger(AuthorizationAdvisor.class);

@SuppressWarnings("unchecked")

private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =

new Class[] {RequiresResource.class};

/**

* Create a new AuthorizationAttributeSourceAdvisor.

*/

public AuthorizationAdvisor() {

setAdvice(new AnnotationsMethodInterceptor());

}

/**

* Returns <tt>true</tt> if the method has any Shiro annotations, false otherwise.

* The annotations inspected are:

* <ul>

* <li>{@link org.apache.shiro.authz.annotation.RequiresAuthentication RequiresAuthentication}</li>

* <li>{@link org.apache.shiro.authz.annotation.RequiresUser RequiresUser}</li>

* <li>{@link org.apache.shiro.authz.annotation.RequiresGuest RequiresGuest}</li>

* <li>{@link org.apache.shiro.authz.annotation.RequiresRoles RequiresRoles}</li>

* <li>{@link org.apache.shiro.authz.annotation.RequiresPermissions RequiresPermissions}</li>

* </ul>

*

* @param method the method to check for a Shiro annotation

* @param targetClass the class potentially declaring Shiro annotations

&n
3ff0
bsp; * @return <tt>true</tt> if the method has a Shiro annotation, false otherwise.

* @see org.springframework.aop.MethodMatcher#matches(java.lang.reflect.Method, Class)

*/

public boolean matches(Method method, Class<?> targetClass) {

Method m = method;

if ( isAuthzAnnotationPresent(m) ) {

return true;

}

//The 'method' parameter could be from an interface that doesn't have the annotation.

//Check to see if the implementation has it.

if ( targetClass != null) {

try {

m = targetClass.getMethod(m.getName(), m.getParameterTypes());

if ( isAuthzAnnotationPresent(m) ) {

return true;

}

} catch (NoSuchMethodException ignored) {

log.error("targetClass is null");

//default return value is false. If we can't find the method, then obviously

//there is no annotation, so just use the default return value.

}

}

return false;

}

private boolean isAuthzAnnotationPresent(Method method) {

for( Class<? extends Annotation> annClass : AUTHZ_ANNOTATION_CLASSES ) {

Annotation a = AnnotationUtils.findAnnotation(method, annClass);

if ( a != null ) {

return true;

}

}

return false;

}

RequiresResource这个是自定义的注解类;matches匹配方法注解假如返回true,就会进入拦截器AnnotationsMethodInterceptor,拦截器方法如下
public class AnnotationsMethodInterceptor extends MethodInterceptorSupport implements MethodInterceptor {

protected Collection<AuthorizingAnnotationMethodInterceptor> metho
3ff0
dInterceptors;

public AnnotationsMethodInterceptor() {

List<AuthorizingAnnotationMethodInterceptor> interceptors = new ArrayList<AuthorizingAnnotationMethodInterceptor>(

5);

AnnotationResolver resolver = new SpringAnnotationResolver();

interceptors.add(new RequiresResourceMethodInterceptor(resolver));

setMethodInterceptors(interceptors);

}

/**

* Returns the method interceptors to execute for the annotated method.

* <p/>

* Unless overridden by the

* {@link #setMethodInterceptors(java.util.Collection)} method, the default

* collection contains a {@link RoleAnnotationMethodInterceptor

* RoleAnnotationMethodInterceptor} and a

* {@link PermissionAnnotationMethodInterceptor

* PermissionAnnotationMethodInterceptor} to support role and permission

* annotations automatically.

*

* @return the method interceptors to execute for the annotated method.

*/

public Collection<AuthorizingAnnotationMethodInterceptor> getMethodInterceptors() {

return methodInterceptors;

}

/**

* Sets the method interceptors to execute for the annotated method.

*

* @param methodInterceptors

* the method interceptors to execute for the annotated method.

* @see #getMethodInterceptors()

*/

public void setMethodInterceptors(Collection<AuthorizingAnnotationMethodInterceptor> methodInterceptors) {

this.methodInterceptors = methodInterceptors;

}

/**

* Creates a {@link MethodInvocation MethodInvocation} that wraps an

* {@link org.aopalliance.intercept.MethodInvocation

* org.aopalliance.intercept.MethodInvocation} instance, enabling Shiro

* Annotations in <a href="http://aopalliance.sourceforge.net/">AOP

* Alliance</a> environments (Spring, etc).

*

* @param implSpecificMethodInvocation

* AOP Alliance {@link org.aopalliance.intercept.MethodInvocation

* MethodInvocation}

* @return a Shiro {@link MethodInvocation MethodInvocation} instance that

* wraps the AOP Alliance instance.

*/

protected MethodInvocation createMethodInvocation(Object implSpecificMethodInvocation) {

final org.aopalliance.intercept.MethodInvocation mi = (org.aopalliance.intercept.MethodInvocation) implSpecificMethodInvocation;

return new MethodInvocation() {

public Method getMethod() {

return mi.getMethod();

}

public Object[] getArguments() {

return mi.getArguments();

}

public String toString() {

return "Method invocation [" + mi.getMethod() +
3ff8
"]";

}

public Object proceed() throws Throwable {

return mi.proceed();

}

public Object getThis() {

return mi.getThis();

}

};

}

/**

* Simply casts the method argument to an

* {@link org.aopalliance.intercept.MethodInvocation

* org.aopalliance.intercept.MethodInvocation} and then calls

* <code>methodInvocation.{@link org.aopalliance.intercept.MethodInvocation#proceed proceed}()</code>

*

* @param aopAllianceMethodInvocation

* the {@link org.aopalliance.intercept.MethodInvocation

* org.aopalliance.intercept.MethodInvocation}

* @return the {@link org.aopalliance.intercept.MethodInvocation#proceed()

* org.aopalliance.intercept.MethodInvocation.proceed()} method call

* result.

* @throws Throwable

* if the underlying AOP Alliance <code>proceed()</code> call

* throws a <code>Throwable</code>.

*/

protected Object continueInvocation(Object aopAllianceMethodInvocation) throws Throwable {

MethodInvocation mi = (MethodInvocation) aopAllianceMethodInvocation;

return mi.proceed();

}

/*

* (non-Javadoc) 获取对应的注解并解析

*/

protected boolean assertAuthorized(MethodInvocation methodInvocation) throws AuthorizationException {

// default implementation just ensures no deny votes are cast:

boolean b = true;

Collection<AuthorizingAnnotationMethodInterceptor> aamis = getMethodInterceptors();

if (aamis != null && !aamis.isEmpty()) {

for (AuthorizingAnnotationMethodInterceptor aami : aamis) {

if (aami.supports(methodInvocation)) {

b = aami.assertAuthorized(methodInvocation);

}

}

}

return b;

}

@Override

public Object invoke(org.aopalliance.intercept.MethodInvocation invocation) throws Throwable {

MethodInvocation mi = createMethodInvocation(invocation);

if (assertAuthorized(mi)) {

return mi.proceed();

} else {

return null;

}

}

}
大部分代码来源shiro,这里不详细说
4000
明了就,需要注意的是红色区域内,假如为true,方法正常往下走(客户端访问的方法),假如为false,不往下进行,什么也不返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: