这个稍微有一点复杂,我是通过AOP来实现的,前半部分跟上一章类似,主要在配置上有点不同
读取方法与权限对应列表DAO
- public List<Map<String,String>> getMethodResourceMapping(){
- String sql = "SELECT S3.RESOURCE_PATH,S2.AUTHORITY_MARK FROM SYS_AUTHORITIES_RESOURCES S1 "+
- "JOIN SYS_AUTHORITIES S2 ON S1.AUTHORITY_ID = S2.AUTHORITY_ID "+
- "JOIN SYS_RESOURCES S3 ON S1.RESOURCE_ID = S3.RESOURCE_ID AND S3.RESOURCE_TYPE='METHOD' ORDER BY S3.PRIORITY DESC";
- List<Map<String,String>> list = new ArrayList<Map<String,String>>();
- Query query = this.entityManager.createNativeQuery(sql);
- List<Object[]> result = query.getResultList();
- Iterator<Object[]> it = result.iterator();
- while(it.hasNext()){
- Object[] o = it.next();
- Map<String,String> map = new HashMap<String,String>();
- map.put("resourcePath", (String)o[0]);
- map.put("authorityMark", (String)o[1]);
- list.add(map);
- }
- return list;
- }
MethodKey用来做主键用的
- public class MethodKey {
- private String className;
- private String methodName;
- public MethodKey(){};
- public MethodKey(String fullName){
- this.className = StringUtils.stripFilenameExtension(fullName);
- this.methodName = StringUtils.getFilenameExtension(fullName);
- };
- public MethodKey(Method method) {
- super();
- this.className = method.getDeclaringClass().getName();
- this.methodName = method.getName();
- }
- public String getClassName() {
- return className;
- }
- public void setClassName(String className) {
- this.className = className;
- }
- public String getMethodName() {
- return methodName;
- }
- public void setMethodName(String methodName) {
- this.methodName = methodName;
- }
- public String getFullMethodName(){
- return this.className + "." + this.methodName;
- }
- @Override
- public boolean equals(Object obj) {
- if(!(obj instanceof MethodKey))return false;
- MethodKey target = (MethodKey)obj;
- if(this.className.equals(target.getClassName()) &&
- this.methodName.equals(target.getMethodName()))return true;
- return false;
- }
- }
MethodSecurityMetadataSource
- public class MethodSecurityMetadataSource extends
- AbstractMethodSecurityMetadataSource implements InitializingBean{
- //protected Log logger = LogFactory.getLog(getClass());
- private final static List<ConfigAttribute> NULL_CONFIG_ATTRIBUTE = Collections.emptyList();
- private final static String RES_KEY = "resourcePath";
- private final static String AUTH_KEY = "authorityMark";
- private Map<MethodKey, Collection<ConfigAttribute>> requestMap;
- @Autowired
- private SysResourceRepository sysResourceRepository;
- /**
- * 根据方法获取到访问方法所需要的权限
- * @param method 访问的方法
- * @param targetClass 方法所属的类
- */
- @Override
- public Collection<ConfigAttribute> getAttributes(Method method,
- Class<?> targetClass) {
- MethodKey key = new MethodKey(method);
- Collection<ConfigAttribute> attrs = NULL_CONFIG_ATTRIBUTE;
- for (Map.Entry<MethodKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
- if (entry.getKey().equals(key)) {
- attrs = entry.getValue();
- break;
- }
- }
- logger.info("METHOD资源:"+key.getFullMethodName()+ " -> " +attrs);
- return attrs;
- }
- /**
- * 获取到所有方法对应的权限集合
- */
- @Override
- public Collection<ConfigAttribute> getAllConfigAttributes() {
- Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
- for (Map.Entry<MethodKey, Collection<ConfigAttribute>> entry : requestMap.entrySet()) {
- allAttributes.addAll(entry.getValue());
- }
- return allAttributes;
- }
- /**
- * 初始化方法权限对应集合,绑定方法权限集合
- */
- @Override
- public void afterPropertiesSet() throws Exception {
- this.requestMap = this.bindRequestMap();
- }
- /**
- * 从数据库中获取方法及权限对应信息
- * @return
- */
- private Map<String,String> loadMehod(){
- Map<String,String> resMap = new LinkedHashMap<String, String>();
- List<Map<String,String>> list = this.sysResourceRepository.getMethodResourceMapping();
- for(Map<String,String> map : list){
- String resourcePath = map.get(RES_KEY);
- String authorityMark = map.get(AUTH_KEY);
- if(resMap.containsKey(resourcePath)){
- String mark = resMap.get(resourcePath);
- resMap.put(resourcePath, mark+","+authorityMark);
- }else{
- resMap.put(resourcePath, authorityMark);
- }
- }
- return resMap;
- }
- /**
- * 封装从数据库中获取的方法权限集合
- * @return
- */
- public Map<MethodKey, Collection<ConfigAttribute>> bindRequestMap(){
- Map<MethodKey, Collection<ConfigAttribute>> resMap =
- new LinkedHashMap<MethodKey, Collection<ConfigAttribute>>();
- Map<String,String> map = this.loadMehod();
- for(Map.Entry<String, String> entry : map.entrySet()){
- MethodKey key = new MethodKey(entry.getKey());
- Collection<ConfigAttribute> atts =
- SecurityConfig.createListFromCommaDelimitedString(entry.getValue());
- resMap.put(key, atts);
- }
- return resMap;
- }
- }
具体配置
- <bean id="methodSecurityInterceptor"
- class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
- <property name="accessDecisionManager" ref="accessDecisionManager" />
- <property name="authenticationManager" ref="authenticationManager" />
- <property name="securityMetadataSource" ref="methodSecurityMetadataSource" />
- </bean>
- <bean id="methodSecurityMetadataSource"
- class="com.zrhis.system.security.MethodSecurityMetadataSource" />
- <aop:config>
- <aop:pointcut id="sevicePointcut"
- expression="execution(* com.zrhis.**.service.*.*(..))"/>
- <aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="sevicePointcut" order="1"/>
- </aop:config>
首先创建pointcut,pointcut是项目中的Service层。然后在advisor中配置拦截器及切面的对应关系
方法的拦截是通过AOP来实现的,方法的拦截到此结束有资源的拦截和方法的拦截基本上就能保证项目的权限能够灵活分配了。