spring security基于aop的方法拦截

spring security基于url的拦截,比较简单一些。就不说了。说一下,基于aop的方法拦截。

1、首先从数据库加载你要拦截的方法,包含包路径+类名+方法名,这个要自己配置到数据库中:

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource;
import org.springframework.security.access.method.MethodSecurityMetadataSource;

import com.vteba.user.service.IAuthoritiesService;

/**
 * 方法级别的权限控制,元数据加载。
 * @author yinlei
 * 2012-4-4 下午5:54:26
 */
public class MethodSecurityMetadataSourceImpl extends AbstractMethodSecurityMetadataSource implements MethodSecurityMetadataSource {
	public static final String SHARP = "#";
	
	private IAuthoritiesService authoritiesServiceImpl;
	private Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
	
	public MethodSecurityMetadataSourceImpl(
			IAuthoritiesService authoritiesServiceImpl) {
		super();
		this.authoritiesServiceImpl = authoritiesServiceImpl;
		loadMethodAuthConfig();// 加载配置
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();  
        for (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {  
            allAttributes.addAll(entry.getValue());  
        }  
        return allAttributes;  
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
		String methodFullPath = targetClass.getName() + SHARP + method.getName();
		return resourceMap.get(methodFullPath);
	}

	public void loadMethodAuthConfig() {
		List<String> authNameList = authoritiesServiceImpl.getAllAuthorities();
		for (String authName : authNameList) {
			ConfigAttribute ca = new SecurityConfig(authName);// eg:ROLE_ADMIN
			List<String> resourceList = authoritiesServiceImpl.getMethodByAuthName(authName);
			for (String url : resourceList) {
				// 该资源和权限是否有对应关系,如果已经存在,则将新权限添加到对应的资源上(这个资源需要哪些权限)
				if (resourceMap.containsKey(url)) {
					Collection<ConfigAttribute> attributes = resourceMap.get(url);
					attributes.add(ca);
					resourceMap.put(url, attributes);
				} else {// 如果是新资源,则将权限添加到对应的资源上
					Collection<ConfigAttribute> atts = new HashSet<ConfigAttribute>();
					atts.add(ca);
					resourceMap.put(url, atts);
				}
			}
		}
	}
}

这个 就得到了,所有要拦截的,所有的方法的元数据。


2、配置spring的拦截器,如下

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;

import com.vteba.security.spring.meta.MethodSecurityMetadataSourceImpl;

/**
 * 基于AOP的方法级别的spring security拦截器。
 * @author yinlei
 * @date 2012-04-04
 */
public class MethodSecurityInterceptorImpl extends AbstractSecurityInterceptor {
	private MethodSecurityMetadataSourceImpl methodSecurityMetadataSourceImpl;
	
	@Override
	public Class<?> getSecureObjectClass() {
		return MethodInvocation.class;
	}

	@Override
	public SecurityMetadataSource obtainSecurityMetadataSource() {
		return methodSecurityMetadataSourceImpl;
	}

	public void setMethodSecurityMetadataSourceImpl(
			MethodSecurityMetadataSourceImpl methodSecurityMetadataSourceImpl) {
		this.methodSecurityMetadataSourceImpl = methodSecurityMetadataSourceImpl;
	}

}

这里面的元数据,就是1中加载的。


3、配置切点,这个可以自由配置。例如:

<!-- 加载基于aop的方法级别的元数据 -->
<!-- 	<bean id="methodSecurityMetadataSourceImpl" class="com.vteba.security.spring.meta.MethodSecurityMetadataSourceImpl"> -->
<!-- 		<constructor-arg ref="authoritiesServiceImpl"/> -->
<!-- 	</bean> -->
	
	<!-- 基于aop的方法级别的拦截器 -->
<!-- 	<bean id="methodSecurityInterceptorImpl" class="com.vteba.security.spring.interceptor.MethodSecurityInterceptorImpl"> -->
<!-- 		<property name="authenticationManager" ref="org.springframework.security.authenticationManager"/> -->
<!-- 		<property name="accessDecisionManager" ref="accessDecisionManagerImpl"/> -->
<!-- 		<property name="securityMetadataSource" ref="methodSecurityMetadataSourceImpl"/> -->
<!-- 	</bean> -->
	
	<!--为指定包下所有类的所有方法应用权限拦截-->
<!-- 	<aop:config> -->
<!-- 		<aop:pointcut expression="execution(* com.vteba.*.*.impl.*.*(..))" id="serviceSECMethodPointCut"/> -->
<!-- 		<aop:pointcut expression="execution(* com.vteba.*.*.service.impl.*.*(..))" id="financeSECMethodPointCut"/> -->
<!-- 		<aop:pointcut expression="execution(* com.vteba.*.*.remote.*.*(..))" id="remoteSECMethodPointCut"/>		 -->
<!-- 		<aop:advisor advice-ref="methodSecurityInterceptorImpl" pointcut-ref="serviceSECMethodPointCut"/> -->
<!-- 		<aop:advisor advice-ref="methodSecurityInterceptorImpl" pointcut-ref="financeSECMethodPointCut"/> -->
<!-- 		<aop:advisor advice-ref="methodSecurityInterceptorImpl" pointcut-ref="remoteSECMethodPointCut"/> -->
<!-- 	</aop:config> -->

这个配置都是注释的,去掉就可以了。


4、这样,在系统启动的时候,首先加载1中元数据,然后系统运行的时候,会被3中配置的切点,拦截到,拦截到以后,就会进入 决策管理器。

验证管理器和决策管理器和基于url的拦截都是公用的。


spring security基于aop的方法拦截,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。