springMVC+mybatis+spring security<三>:使用数据库管理资源
2015-05-26 13:34
447 查看
实际使用中,资源都是保存在数据库中,而不是在XML中进行配置。
使用数据库管理资源时,需要实现FilterInvocationSecurityMetadataSource接口:
以上代码主要的做法就是:
(1)将资源从数据库中查出来,并和其对应的角色做关联,封装到Map<String, Collection<ConfigAttribute>>中;
(2)每次请求到达过滤器后,根据请求的URL去map中匹配对应的权限(即角色)。
在security的配置文件中做相应配置:自己实现的过滤器要在security的之前执行
以上步骤完成后,就可以实现对资源URL的过滤。
在实际使用时,还需要注意到的一个问题就是,在每次分配完权限之后,需重启系统才能生效。这是因为该类初始化之后将资源map加载到了内存中,数据库发生了变化,但内存并没有刷新。
基于以上原理,解决该问题的办法就是:在每次分配完权限之后,重新加载map,这也是代码中加入expire属性的原因。
这样可以做到即使不用LogOut更不用重启项目,也可以动态的刷新权限资源。
使用数据库管理资源时,需要实现FilterInvocationSecurityMetadataSource接口:
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource, InitializingBean { private boolean expire = false; private final static List<ConfigAttribute> NULL_CONFIG_ATTRIBUTE = Collections.emptyList(); private Map<String, Collection<ConfigAttribute>> requestMap; private AntPathMatcher urlMatcher = new AntPathMatcher(); @Autowired private SysResourceService sysResourceService; /** * 获取所有权限集合 */ @Override public Collection<ConfigAttribute> getAllConfigAttributes() { Set<ConfigAttribute> set = new HashSet<ConfigAttribute>(); for (Map.Entry<String, Collection<ConfigAttribute>> entry : requestMap.entrySet()) { set.addAll(entry.getValue()); } return set; } /** * 根据request请求获取访问资源所需权限 */ @Override public Collection<ConfigAttribute> getAttributes(Object obj) throws IllegalArgumentException { //刷新资源 if(isExpire()){ this.requestMap.clear(); expire = false; } //若map为空,则重新加载 if(this.requestMap==null || this.requestMap.isEmpty()){ this.requestMap = bindRequestMap(); } String URL = ((FilterInvocation) obj).getRequestUrl(); if (URL.contains("&")) { URL = URL.substring(0, URL.indexOf("&")); } Collection<ConfigAttribute> attrs = NULL_CONFIG_ATTRIBUTE; for (Map.Entry<String, Collection<ConfigAttribute>> entry : requestMap.entrySet()) { if (urlMatcher.match(URL, entry.getKey())) { attrs = entry.getValue(); break; } } return attrs; } @Override public boolean supports(Class<?> arg0) { return FilterInvocation.class.isAssignableFrom(arg0); } @Override public void afterPropertiesSet() throws Exception { this.requestMap = this.bindRequestMap(); } protected Map<String, Collection<ConfigAttribute>> bindRequestMap() { Map<String, Collection<ConfigAttribute>> map = new LinkedHashMap<String, Collection<ConfigAttribute>>(); Map<String, String> sourceMap = this.loadResouece(); for (Map.Entry<String, String> entry : sourceMap.entrySet()) { String key = entry.getKey(); Collection<ConfigAttribute> attr = new ArrayList<ConfigAttribute>(); attr = SecurityConfig.createListFromCommaDelimitedString(entry.getValue()); map.put(key, attr); } return map; } /** * 从数据库中加载权限和资源的对应列表 * * @return */ private Map<String, String> loadResouece() { Map<String, String> map = new LinkedHashMap<String, String>(); List<SysResource> list = sysResourceService.getAllResRole(); if (list != null && list.size() > 0) { for (SysResource r : list) { String path = r.getResourcePath(); String code = r.getGroupCode(); if (map.containsKey(path)) { String existCode = map.get(path); map.put(path, existCode + "," + code); } else { map.put(path, code); } } } return map; } public boolean isExpire() { return expire; }
public void expireNow(){ this.expire = true; } }
以上代码主要的做法就是:
(1)将资源从数据库中查出来,并和其对应的角色做关联,封装到Map<String, Collection<ConfigAttribute>>中;
(2)每次请求到达过滤器后,根据请求的URL去map中匹配对应的权限(即角色)。
在security的配置文件中做相应配置:自己实现的过滤器要在security的之前执行
<!-- 自定义过滤器,在security的过滤器之前执行 --> <custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
</pre><pre name="code" class="html"><beans:bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> <beans:property name="securityMetadataSource" ref="securityMetadataSource"></beans:property> <beans:property name="accessDecisionManager" ref="accessDecisionManager"></beans:property> <beans:property name="authenticationManager" ref="authenticationManager"></beans:property> </beans:bean>
以上步骤完成后,就可以实现对资源URL的过滤。
在实际使用时,还需要注意到的一个问题就是,在每次分配完权限之后,需重启系统才能生效。这是因为该类初始化之后将资源map加载到了内存中,数据库发生了变化,但内存并没有刷新。
基于以上原理,解决该问题的办法就是:在每次分配完权限之后,重新加载map,这也是代码中加入expire属性的原因。
// 数据库权限发生变化,需要刷新内存 WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request .getServletContext()); MySecurityMetadataSource source = (MySecurityMetadataSource)wac.getBean("securityMetadataSource"); source.expireNow();
这样可以做到即使不用LogOut更不用重启项目,也可以动态的刷新权限资源。
相关文章推荐
- spring<mvc:resources> 标签的使用 静态资源的访问
- 架构搭起后 为了实现 对静态资源文件的访问 spring_mvc.xml 添加<mvc:default-servlet-handler /> 但却再也无法访问到controller
- springboot+springmvc+mybatis 使用注解对数据库的增、改和查操作
- springmvc<一>一种资源返回多种形式【ContentNegotiatingViewResolver】
- Java后台开发<二>:Spirng+SpringMVC+Maven+Mybatis+MySQL项目搭建
- 关于spring 3.0.5的<mvc:resources> 标签的使用
- spring mvc <mvc:annotation-driven>配置使用出现问题
- 关于spring <mvc:resources> 标签的使用
- MVC静态资源映射 <mvc:resources> 标签的使用
- spring mvc <mvc:annotation-driven>配置使用出现故障
- spring使用<mvc:annotation-driven/>来解决定时任务
- springMVC <mvc:interceptors>拦截器的使用
- 关于spring 3.0.5的 <mvc:resources mapping="***" location="***">标签的使用
- 整理springmvc+mybatis+velocity的整合<一>
- 整合springmvc+mybatis+veloctiy<二>
- 整合springmvc+mybatis+veloctiy<三>
- spring <context:component-scan />及<mvc:annotation-driven />使用说明
- spring整合mybatis使用<context:property-placeholder>时的坑
- Spring整合Mybatis使用<context:property-placeholder>时的坑
- spring3 jsp页面使用<form:form modelAttribute="xxxx" action="xxxx">报错,附连接数据库的spring MVC annotation 案例