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的拦截都是公用的。