Spring Security教程(11)---- 使用数据库来管理资源

这个可以说是SpringSecurity最核心的东西,在项目中资源很多肯定不能一一配置到配置文件中,所以用数据库来管理资源是必然的。这个也很容易实现。表结构已经在之前都创建过了。

首先我们要来从数据库中获取到资源与权限的对应列表,这个在dao层实现即可需要获取到url地址和AUTH_**这种权限标识,注意:不是权限ID和资源ID。

	public List> getURLResourceMapping(){
		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 S3.RESOURCE_TYPE='URL' ORDER BY S3.PRIORITY DESC";
		
		List> list = new ArrayList>();
		
		Query query = this.entityManager.createNativeQuery(sql);
		List result = query.getResultList();
		Iterator it = result.iterator();
		
		while(it.hasNext()){
			Object[] o = it.next();
			Map map = new HashMap();
			map.put("resourcePath", (String)o[0]);
			map.put("authorityMark", (String)o[1]);
			list.add(map);
		}
		
		return list;
	}
创建SecurityMetadataSource供过滤器使用,SecurityMetadataSource需要实现FilterInvocationSecurityMetadataSource

public class URLFilterInvocationSecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource,InitializingBean {

	protected final Log logger = LogFactory.getLog(getClass());
	
	private final static List NULL_CONFIG_ATTRIBUTE = Collections.emptyList();
	//权限集合
	private Map> requestMap;
	
	@Autowired
	private SysResourceRepository sysResourceRepository;
	
	/* (non-Javadoc)
	 * @see org.springframework.security.access.SecurityMetadataSource#getAttributes(java.lang.Object)
	 */
	@Override
	public Collection getAttributes(Object object)
			throws IllegalArgumentException {
		final HttpServletRequest request = ((FilterInvocation) object).getRequest();
        
        Collection attrs = NULL_CONFIG_ATTRIBUTE;
        
        for (Map.Entry> entry : requestMap.entrySet()) {
            if (entry.getKey().matches(request)) {
            	attrs =  entry.getValue();
            	break;
            }
        }
        logger.info("URL资源:"+request.getRequestURI()+ " -> " + attrs);
        return attrs;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.access.SecurityMetadataSource#getAllConfigAttributes()
	 */
	@Override
	public Collection getAllConfigAttributes() {
		Set allAttributes = new HashSet();

        for (Map.Entry> entry : requestMap.entrySet()) {
            allAttributes.addAll(entry.getValue());
        }

        return allAttributes;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.access.SecurityMetadataSource#supports(java.lang.Class)
	 */
	@Override
	public boolean supports(Class clazz) {
		return FilterInvocation.class.isAssignableFrom(clazz);
	}
	
	private Map loadResuorce(){
		Map map = new LinkedHashMap();
		
		List> list = this.sysResourceRepository.getURLResourceMapping();
		Iterator> it = list.iterator();
		while(it.hasNext()){
			Map rs = it.next();
			String resourcePath = rs.get("resourcePath");
			String authorityMark = rs.get("authorityMark");
			
			if(map.containsKey(resourcePath)){
				String mark = map.get("resourcePath");
				map.put(resourcePath, mark+","+authorityMark);
			}else{
				map.put(resourcePath, authorityMark);
			}
		}
		return map;
	}
	
	protected Map> bindRequestMap(){
		Map> map = 
				new LinkedHashMap>();
		
		Map resMap = this.loadResuorce();
		for(Map.Entry entry:resMap.entrySet()){
			String key = entry.getKey();
			Collection atts = new ArrayList();
			atts = SecurityConfig.createListFromCommaDelimitedString(entry.getValue());
			map.put(new AntPathRequestMatcher(key), atts);
		}
		
		return map;
	}

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		this.requestMap = this.bindRequestMap();
		logger.info("资源权限列表"+this.requestMap);
	}
	
	public void refreshResuorceMap(){
		this.requestMap = this.bindRequestMap();
	}

}
bindRequestMap需要在类初始化的时候就完成,但是这个不能写在构造函数中,因为构造函数执行是SysResourceRepository还没有注入过来。所以就通过实现InitializingBean把初始化操作放在afterPropertiesSet方法中。

getAllConfigAttributes:获取所有权限集合

getAttributes:根据request请求获取访问资源所需权限

代码很简单,很容易看懂,就不再多做解释,下面看配置文件

	
		
		
		
		
		
		
		
		
			
	

	
		
		
		
	
	
	

通过配置custom-filter来增加过滤器,before="FILTER_SECURITY_INTERCEPTOR"表示在SpringSecurity默认的过滤器之前执行。

FilterSecurityInterceptor还用SpringSecurity默认的就可以了,这个是没有必要自己写的只要在SecurityMetadataSource处理好资源与权限的对应关系就可以了。

到此为止SpringSecurity框架已基本完善,可以说在项目中用已经没什么问题了。


你可能感兴趣的:(Spring Security教程(11)---- 使用数据库来管理资源)