Spring Security教程(12)---- 使用数据库来管理方法

这个稍微有一点复杂,我是通过AOP来实现的,前半部分跟上一章类似,主要在配置上有点不同

读取方法与权限对应列表DAO

  1. public List<Map<String,String>> getMethodResourceMapping(){  
  2.     String sql = "SELECT S3.RESOURCE_PATH,S2.AUTHORITY_MARK FROM SYS_AUTHORITIES_RESOURCES S1 "+  
  3.             "JOIN SYS_AUTHORITIES S2 ON S1.AUTHORITY_ID = S2.AUTHORITY_ID "+  
  4.             "JOIN SYS_RESOURCES S3 ON S1.RESOURCE_ID = S3.RESOURCE_ID AND S3.RESOURCE_TYPE='METHOD' ORDER BY S3.PRIORITY DESC";  
  5.       
  6.     List<Map<String,String>> list = new ArrayList<Map<String,String>>();  
  7.       
  8.     Query query = this.entityManager.createNativeQuery(sql);  
  9.     List<Object[]> result = query.getResultList();  
  10.     Iterator<Object[]> it = result.iterator();  
  11.       
  12.     while(it.hasNext()){  
  13.         Object[] o = it.next();  
  14.         Map<String,String> map = new HashMap<String,String>();  
  15.         map.put("resourcePath", (String)o[0]);  
  16.         map.put("authorityMark", (String)o[1]);  
  17.         list.add(map);  
  18.     }  
  19.       
  20.     return list;  
  21. }  
这里只针对方法名拦截,对于同一个类中的同名方法统统作为一个方法拦截。如果需要更细粒度的拦截,即拦截到参数,请在完成这个内容之后自行进行深入的研究。

MethodKey用来做主键用的

  1. public class MethodKey {  
  2.     private String className;  
  3.     private String methodName;  
  4.       
  5.     public MethodKey(){};  
  6.       
  7.     public MethodKey(String fullName){  
  8.         this.className = StringUtils.stripFilenameExtension(fullName);  
  9.         this.methodName = StringUtils.getFilenameExtension(fullName);  
  10.     };  
  11.       
  12.     public MethodKey(Method method) {  
  13.         super();  
  14.         this.className = method.getDeclaringClass().getName();  
  15.         this.methodName = method.getName();  
  16.     }  
  17.     public String getClassName() {  
  18.         return className;  
  19.     }  
  20.     public void setClassName(String className) {  
  21.         this.className = className;  
  22.     }  
  23.     public String getMethodName() {  
  24.         return methodName;  
  25.     }  
  26.     public void setMethodName(String methodName) {  
  27.         this.methodName = methodName;  
  28.     }  
  29.       
  30.     public String getFullMethodName(){  
  31.         return this.className + "." + this.methodName;  
  32.     }  
  33.       
  34.     @Override  
  35.     public boolean equals(Object obj) {  
  36.         if(!(obj instanceof MethodKey))return false;  
  37.           
  38.         MethodKey target = (MethodKey)obj;  
  39.           
  40.         if(this.className.equals(target.getClassName()) &&   
  41.                 this.methodName.equals(target.getMethodName()))return true;  
  42.           
  43.         return false;  
  44.     }  
  45.       
  46. }  
getDeclaringClass获取到的是接口,这里我们只拦截接口。

MethodSecurityMetadataSource

  1. public class MethodSecurityMetadataSource extends  
  2.         AbstractMethodSecurityMetadataSource implements InitializingBean{  
  3.       
  4.     //protected Log logger = LogFactory.getLog(getClass());  
  5.       
  6.     private final static List<ConfigAttribute> NULL_CONFIG_ATTRIBUTE = Collections.emptyList();  
  7.       
  8.     private final static String RES_KEY = "resourcePath";  
  9.     private final static String AUTH_KEY = "authorityMark";  
  10.       
  11.     private Map<MethodKey, Collection<ConfigAttribute>> requestMap;  
  12.       
  13.     @Autowired  
  14.     private SysResourceRepository sysResourceRepository;  
  15.       
  16.     /** 
  17.      * 根据方法获取到访问方法所需要的权限 
  18.      * @param method 访问的方法 
  19.      * @param targetClass 方法所属的类 
  20.      */  
  21.     @Override  
  22.     public Collection<ConfigAttribute> getAttributes(Method method,  
  23.             Class<?> targetClass) {  
  24.         MethodKey key = new MethodKey(method);  
  25.         Collection<ConfigAttribute> attrs = NULL_CONFIG_ATTRIBUTE;  
  26.           
  27.         for (Map.Entry<MethodKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {  
  28.             if (entry.getKey().equals(key)) {  
  29.                 attrs =  entry.getValue();  
  30.                 break;  
  31.             }  
  32.         }  
  33.         logger.info("METHOD资源:"+key.getFullMethodName()+ " -> " +attrs);  
  34.           
  35.         return attrs;  
  36.     }  
  37.   
  38.     /** 
  39.      * 获取到所有方法对应的权限集合 
  40.      */  
  41.     @Override  
  42.     public Collection<ConfigAttribute> getAllConfigAttributes() {  
  43.         Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();  
  44.   
  45.         for (Map.Entry<MethodKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {  
  46.             allAttributes.addAll(entry.getValue());  
  47.         }  
  48.   
  49.         return allAttributes;  
  50.     }  
  51.   
  52.     /** 
  53.      * 初始化方法权限对应集合,绑定方法权限集合 
  54.      */  
  55.     @Override  
  56.     public void afterPropertiesSet() throws Exception {  
  57.         this.requestMap = this.bindRequestMap();  
  58.     }  
  59.       
  60.     /** 
  61.      * 从数据库中获取方法及权限对应信息 
  62.      * @return 
  63.      */  
  64.     private Map<String,String> loadMehod(){  
  65.         Map<String,String> resMap = new LinkedHashMap<String, String>();  
  66.         List<Map<String,String>> list = this.sysResourceRepository.getMethodResourceMapping();  
  67.           
  68.         for(Map<String,String> map : list){  
  69.             String resourcePath = map.get(RES_KEY);  
  70.             String authorityMark = map.get(AUTH_KEY);  
  71.               
  72.             if(resMap.containsKey(resourcePath)){  
  73.                 String mark = resMap.get(resourcePath);  
  74.                 resMap.put(resourcePath, mark+","+authorityMark);  
  75.             }else{  
  76.                 resMap.put(resourcePath, authorityMark);  
  77.             }  
  78.         }  
  79.           
  80.         return resMap;  
  81.     }  
  82.       
  83.     /** 
  84.      * 封装从数据库中获取的方法权限集合 
  85.      * @return 
  86.      */  
  87.     public Map<MethodKey, Collection<ConfigAttribute>> bindRequestMap(){  
  88.         Map<MethodKey, Collection<ConfigAttribute>> resMap =   
  89.                 new LinkedHashMap<MethodKey, Collection<ConfigAttribute>>();  
  90.           
  91.         Map<String,String> map = this.loadMehod();  
  92.         for(Map.Entry<String, String> entry : map.entrySet()){  
  93.             MethodKey key = new MethodKey(entry.getKey());  
  94.             Collection<ConfigAttribute> atts =   
  95.                     SecurityConfig.createListFromCommaDelimitedString(entry.getValue());  
  96.               
  97.             resMap.put(key, atts);  
  98.         }  
  99.           
  100.         return resMap;  
  101.     }  
  102.   
  103. }  
与资源的SecurityMetadataSource类似,只不过拦截方法的SecurityMetadataSource需要继承自AbstractMethodSecurityMetadataSource或实现MethodSecurityMetadataSource

具体配置

  1. <bean id="methodSecurityInterceptor"   
  2.     class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">  
  3.     <property name="accessDecisionManager" ref="accessDecisionManager" />  
  4.     <property name="authenticationManager" ref="authenticationManager" />  
  5.     <property name="securityMetadataSource" ref="methodSecurityMetadataSource" />  
  6. </bean>  
  7.   
  8. <bean id="methodSecurityMetadataSource"  
  9.     class="com.zrhis.system.security.MethodSecurityMetadataSource" />  
  10.   
  11. <aop:config>  
  12.     <aop:pointcut id="sevicePointcut"   
  13.         expression="execution(* com.zrhis.**.service.*.*(..))"/>  
  14.     <aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="sevicePointcut" order="1"/>  
  15. </aop:config>  

首先创建pointcut,pointcut是项目中的Service层。然后在advisor中配置拦截器及切面的对应关系

方法的拦截是通过AOP来实现的,方法的拦截到此结束有资源的拦截和方法的拦截基本上就能保证项目的权限能够灵活分配了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值