spring-security最后一天,今天的主要內(nèi)容是將需要指定權(quán)限才可以訪問的資源放到數(shù)據(jù)庫中,脫離applicationContext.xml配置文件。然后我們將近兩天學(xué)習(xí)的srping-security整合到教育辦公系統(tǒng)中。
我們繼續(xù)昨天的內(nèi)容,將資源文件信息保存到數(shù)據(jù)庫中。
1.applicationContext.xml
將昨天applicationContext.xml“配置SpringSecurity的http安全服務(wù)”部分的內(nèi)容替換為:
<sec:http auto-config="true" session-fixation-protection="none" /> <bean class="org.springframework.security.intercept.web.FilterSecurityInterceptor" autowire="byType"> <sec:custom-filter before="AUTHENTICATION_PROCESSING_FILTER"/> <property name="objectDefinitionSource" ref="objectDefinitionSource"/> </bean> |
這里的objectDefinitionSource是下邊的類,cutom-filter是在調(diào)用AUTHENTICATION_PROCESSING_FILTER過濾器之前調(diào)用FilterSecurityInterceptor。
2.添加數(shù)據(jù)表
resc表與role表是多對多關(guān)系。
1).resc
2).resc_role
3.相關(guān)類
要讓spring-security可以從數(shù)據(jù)庫中獲取相關(guān)資源信息,我們必須編寫一個實現(xiàn)FactoryBean接口的類。
package cn.itcast.cc.spring.security; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.Resource; import org.springframework.beans.factory.FactoryBean; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.ConfigAttributeEditor; import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource; import org.springframework.security.intercept.web.RequestKey; import org.springframework.security.util.AntUrlPathMatcher; import org.springframework.security.util.UrlMatcher; import org.springframework.stereotype.Component; @Component("objectDefinitionSource") public class DefaultFilterInvocationDefinitionSourceImpl implements FactoryBean { @Resource ResourceDetailsService resourceDetailsService; private UrlMatcher getUrlMatcher() { UrlMatcher urlMatcher = new AntUrlPathMatcher(); return urlMatcher; } @Override public Object getObject() throws Exception { UrlMatcher urlMatcher = this.getUrlMatcher(); // 獲取數(shù)據(jù)Map Map<String, String> srcMap = resourceDetailsService.buildRequestMap(); LinkedHashMap<RequestKey, Object> requestMap = new LinkedHashMap<RequestKey, Object>(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); // 轉(zhuǎn)換數(shù)據(jù)Map for (Map.Entry<String, String> entry : srcMap.entrySet()) { String url = entry.getKey(); String roles = entry.getValue(); if (roles != null) { editor.setAsText(roles); requestMap.put(new RequestKey(url), editor.getValue()); } else { requestMap.put(new RequestKey(url), ConfigAttributeDefinition.NO_ATTRIBUTES); } } // 生成并返回對象 return new DefaultFilterInvocationDefinitionSource(urlMatcher, requestMap); } @Override public Class getObjectType() { return null; } @Override public boolean isSingleton() { return false; } } |
其中ResourceDetailsService接口的實現(xiàn)類如下:
package cn.itcast.cc.spring.security; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import org.springframework.stereotype.Component; @Component("userDetailsService") public class ResourceDetailsServiceImpl implements ResourceDetailsService { @Resource private SimpleJdbcTemplate jdbcTemplate; @Override public Map<String, String> buildRequestMap() { // 注意:這里需要使用左外連接查詢,是因為有些頁面沒有指定role。 // 即,任何權(quán)限都不可以訪問的頁面! String sql = "SELECT res_string as url,r.name as role " + "FROME resc LEFT JOIN resc_role rr ON rr.resc_id = resc.id " + "LEFT JOIN role r ON rr.role_id = r.id"; List<Map<String, Object>> results = this.jdbcTemplate.queryForList(sql); Map<String, String> srcMap = new HashMap<String, String>(); // 將查詢后的數(shù)據(jù)拼接并放入到Map中 for(Map<String,Object> val:results){ String url = (String) val.get("url"); String role = (String) val.get("role"); if(srcMap.containsKey(url)){ role = srcMap.get(url) + "," + role; } srcMap.put(url, role); } return srcMap; } } |
Spring-security還為我們提供了其他實用的輔助功能,具體的google一下吧!