您的位置:首页 > 编程语言 > Java开发

springMVC+mybatis+spring security<三>:使用数据库管理资源

2015-05-26 13:34 447 查看
实际使用中,资源都是保存在数据库中,而不是在XML中进行配置。

使用数据库管理资源时,需要实现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 security