springnbsp;security总结nbsp;太有用了!!
生活随笔
收集整理的這篇文章主要介紹了
springnbsp;security总结nbsp;太有用了!!
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉至:?http://www.cnblogs.com/yl2755/archive/2012/04/19/2456823.html 謝謝作者!!!
首先導入spring security所需要的jar包?
spring-security-core-2.0.5.RELEASE.jar?
spring-security-core-tiger-2.0.5.RELEASE.jar?
一.配置過濾器?
在web.xml中定義如下過濾器?
? ?
??????? springSecurityFilterChain?
??????? org.springframework.web.filter.DelegatingFilterProxy?
??? ?
??? ?
??????? springSecurityFilterChain?
??????? ?
CREATE TABLE `t_account` (?
? `id` int(11) NOT NULL,?
? `username` varchar(255) default NULL,?
? `password` varchar(255) default NULL,?
? `enabled` int default NULL, ?
? PRIMARY KEY? (`id`)?
??? ) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
??? ?
??? CREATE TABLE `t_role` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL, ?
? `descn` varchar(255) default NULL, ?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_account_role` (?
? `a_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`a_id`,`r_id`),?
? KEY `FK1C2BC9332D31C656` (`r_id`),?
? KEY `FK1C2BC93371CCC630` (`a_id`),?
? CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`),?
? CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
當用戶登錄時,spring security首先判斷用戶是否可以登錄。用戶登錄后spring security獲得該用戶的?
所有權限以判斷用戶是否可以訪問資源。?
spring配置文件中定義?
?
???????
??????? users-by-username-query="select username,password,enabled from t_account where username=?"?
??????? authorities-by-username-query="select r.descn from t_account_role ar join?
???????? t_account a on ar.a_id=a.id join t_role r on ar.r_id=r.id where a.username=?"/>?
??? ?
????
??? users-by-username-query:根據用戶名查找用戶?
??? authorities-by-username-query:根據用戶名查找這個用戶所有的角色名,將用戶訪問的URL地址和?
??? 查詢結果與標簽進行匹配。?
??? 匹配成功就允許訪問,否則就返回到提示頁面。?
????
??? 在標簽中添加登錄頁面等信息?
??? ?
??? ? ?
??????? ?
??????? CREATE TABLE `t_account` (?
? `id` int(11) NOT NULL,?
? `username` varchar(255) default NULL,?
? `password` varchar(255) default NULL,?
? `enabled` int default NULL, ?
? PRIMARY KEY? (`id`)?
??? ) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
??? ?
??? CREATE TABLE `t_role` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL, ?
? `descn` varchar(255) default NULL, ?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_account_role` (?
? `a_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`a_id`,`r_id`),?
? KEY `FK1C2BC9332D31C656` (`r_id`),?
? KEY `FK1C2BC93371CCC630` (`a_id`),?
? CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`),?
? CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_module` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL,?
? `address` varchar(255) default NULL,?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_module_role` (?
? `m_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`m_id`,`r_id`),?
? KEY `FKA713071E2D31C656` (`r_id`),?
? KEY `FKA713071ED78C9071` (`m_id`),?
? CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`),?
? CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
??? insert into t_module values(1,'部門管理','/dept.jsp');?
??? insert into t_module values(2,'人員管理','/emp.jsp');?
????
??? insert into `t_module_role` values(1,1);?
??? insert into `t_module_role` values(1,2);?
??? insert into `t_module_role` values(2,1);?
????
1.在自定義的過濾器中獲取資源的URL地址和角色名以取代spring配置文件中原有的?
??? 過濾器代碼:?
import java.sql.ResultSet;?
import java.sql.SQLException;?
import java.util.LinkedHashMap;?
import java.util.List;?
import java.util.Map;?
import javax.sql.DataSource;?
import org.springframework.beans.factory.FactoryBean;?
import org.springframework.jdbc.core.support.JdbcDaoSupport;?
import org.springframework.jdbc.object.MappingSqlQuery;?
import org.springframework.security.ConfigAttributeDefinition;?
import org.springframework.security.ConfigAttributeEditor;?
import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;?
import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;?
import org.springframework.security.intercept.web.RequestKey;?
import org.springframework.security.util.AntUrlPathMatcher;?
import org.springframework.security.util.UrlMatcher;?
public class JdbcFilterInvocationDefinitionSourceFactoryBean?
??? extends JdbcDaoSupport implements FactoryBean {?
??? private String resourceQuery;?
??? public boolean isSingleton() {?
??????? return true;?
??? }?
??? public Class getObjectType() {?
??????? return FilterInvocationDefinitionSource.class;?
??? }?
??? public Object getObject() {?
??????? return new DefaultFilterInvocationDefinitionSource(this?
??????????? .getUrlMatcher(), this.buildRequestMap());?
??? }?
??? protected Map findResources() {?
??????? ResourceMapping resourceMapping = new ResourceMapping(getDataSource(),?
??????????????? resourceQuery);?
??????? Map resourceMap = new LinkedHashMap();?
??????? for (Resource resource : (List) resourceMapping.execute()) {?
??????????? String url = resource.getUrl();?
??????????? String role = resource.getRole();?
??????????? if (resourceMap.containsKey(url)) {?
??????????????? String value = resourceMap.get(url);?
??????????????? resourceMap.put(url, value + "," + role);?
??????????? } else {?
??????????????? resourceMap.put(url, role);?
??????????? }?
??????? }?
??????? return resourceMap;?
??? }?
??? protected LinkedHashMap buildRequestMap() {?
??????? LinkedHashMap requestMap = null;?
??????? requestMap = new LinkedHashMap();?
??????? ConfigAttributeEditor editor = new ConfigAttributeEditor();?
??????? Map resourceMap = this.findResources();?
??????? for (Map.Entry entry : resourceMap.entrySet()) {?
??????????? RequestKey key = new RequestKey(entry.getKey(), null);?
??????????? editor.setAsText(entry.getValue());?
??????????? requestMap.put(key,?
??????????????? (ConfigAttributeDefinition) editor.getValue());?
??????? }?
??????? return requestMap;?
??? }?
??? protected UrlMatcher getUrlMatcher() {?
??????? return new AntUrlPathMatcher();?
??? }?
??? public void setResourceQuery(String resourceQuery) {?
??????? this.resourceQuery = resourceQuery;?
??? }?
??? private class Resource {?
??????? private String url;?
??????? private String role;?
??????? public Resource(String url, String role) {?
??????????? this.url = url;?
??????????? this.role = role;?
??????? }?
??????? public String getUrl() {?
??????????? return url;?
??????? }?
??????? public String getRole() {?
??????????? return role;?
??????? }?
??? }?
??? private class ResourceMapping extends MappingSqlQuery {?
??????? protected ResourceMapping(DataSource dataSource,?
??????????? String resourceQuery) {?
??????????? super(dataSource, resourceQuery);?
??????????? compile();?
??????? }?
??????? protected Object mapRow(ResultSet rs, int rownum)?
??????????? throws SQLException {?
??????????? String url = rs.getString(1);?
??????????? String role = rs.getString(2);?
??????????? Resource resource = new Resource(url, role);?
????????????
??????????? return resource;?
??????? }?
??? }?
}?
將自定義的過濾器放入到原有的spring security過濾器鏈中(在spring配置文件中配置)?
定義自定義過濾器(sql語句用于查詢資源的URL地址 如:/index.jsp 和角色名 如ROLE_USER)?
??????? class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean">?
??????? ?
??????? ??????????? select m.address,r.descn?
from t_module_role mr?
join t_module m on mr.m_id=m.id?
join t_role r on mr.r_id=r.id;?
??????? "/>?
??? ?
? 將自定義過濾器放入過濾器鏈中?
?
??????? class="org.springframework.security.intercept.web.FilterSecurityInterceptor" >?
??????? ?
??????? ?
??? ?
??? 注意:FilterSecurityInterceptor過濾器會向request中寫入一個標記,用于標記是否已經控制了當前請求,以避免對同一請求多次處理,導致第2個FilterSecurityInterceptor不會再次執行。?
??? 在中不需要再定義,如下:?
??? ?
???????
??????????????????? authentication-failure-url="/error.jsp"?
??????????????????? default-target-url="/index.jsp" />?
????????????????????
??? ?
??? 自定義的過濾器就從配置文件中讀取sql,查詢結果就是角色和資源,用戶登錄時就在session中保存了用戶的角色。?
??? 注意:intercept-url的先后順序,spring security使用第一個能匹配的intercept-url標簽進行權限控制。?
??? 現在intercept-url來源于數據庫,所以在sql查詢時注意角色和資源的順序。?
??? 建議在角色和資源的中間表中添加1個字段用于標識順序,(按從嚴到寬的順序)?
??? 表結構修改如下:?
??? ?
CREATE TABLE `t_module_role` (?
? `m_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? `priority` int(11) default NULL, ?
? PRIMARY KEY? (`m_id`,`r_id`),?
? KEY `FKA713071E2D31C656` (`r_id`),?
? KEY `FKA713071ED78C9071` (`m_id`),?
? CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`),?
? CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
數據如下:?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
??? insert into t_module values(1,'部門管理','/dept.jsp');?
??? insert into t_module values(2,'人員管理','/emp.jsp');?
????
??? insert into `t_module_role` values(1,1,3);?
??? insert into `t_module_role` values(1,2,2);?
??? insert into `t_module_role` values(2,1,1);?
????
??? 自定義過濾器修改如下:?
???
??????? class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean">?
??????? ?
??????? ??????????? select m.address,r.descn?
from t_module_role mr?
join t_module m on mr.m_id=m.id?
join t_role r on mr.r_id=r.id?
order by mr.priority?
??????? "/>?
??? ?
????
??? 如果持久層使用的是hibernate,那么只需要給自定義過濾器注入1個hibernateTemplate.?
??? 在自定義過濾器中就不需要再使用mapRow的方式。而是直接獲取url和角色名即可。?
??? 例如:?
??? public class ModuleFilter implements FactoryBean {?
private String resourceQuery;?
??? public boolean isSingleton() {?
??????? return true;?
??? }?
??? public Class getObjectType() {?
??????? return FilterInvocationDefinitionSource.class;?
??? }?
??? public Object getObject() {?
??????? return new DefaultFilterInvocationDefinitionSource(this?
??????????? .getUrlMatcher(), this.buildRequestMap());?
??? }?
??? protected Map findResources() {?
??????? ResourceMapping resourceMapping = new ResourceMapping();?
??????? Map resourceMap = new LinkedHashMap();?
??????? for (Resource resource : (List) resourceMapping.execute()) {?
??????????? String url = resource.getUrl();?
??????????? String role = resource.getRole();?
??????????? if (resourceMap.containsKey(url)) {?
??????????????? String value = resourceMap.get(url);?
??????????????? resourceMap.put(url, value + "," + role);?
??????????? } else {?
??????????????? resourceMap.put(url, role);?
??????????? }?
??????? }?
??????? return resourceMap;?
??? }?
??? protected LinkedHashMap buildRequestMap() {?
??????? LinkedHashMap requestMap = null;?
??????? requestMap = new LinkedHashMap();?
??????? ConfigAttributeEditor editor = new ConfigAttributeEditor();?
??????? Map resourceMap = this.findResources();?
??????? for (Map.Entry entry : resourceMap.entrySet()) {?
??????????? RequestKey key = new RequestKey(entry.getKey(), null);?
??????????? editor.setAsText(entry.getValue());?
??????????? requestMap.put(key,?
??????????????? (ConfigAttributeDefinition) editor.getValue());?
??????? }?
??????? return requestMap;?
??? }?
??? protected UrlMatcher getUrlMatcher() {?
??????? return new AntUrlPathMatcher();?
??? }?
??? public void setResourceQuery(String resourceQuery) {?
??????? this.resourceQuery = resourceQuery;?
??? }?
??? private class Resource {?
??????? private String url;?
??????? private String role;?
??????? public Resource(String url, String role) {?
??????????? this.url = url;?
??????????? this.role = role;?
??????? }?
??????? public String getUrl() {?
??????????? return url;?
??????? }?
??????? public String getRole() {?
??????????? return role;?
??????? }?
??? }?
??? private class ResourceMapping{?
??????? public List execute(){?
??????? List rlist = new ArrayList();?
??????? List list = hibernateTemplate.find(resourceQuery);?
??????? for(int i=0;i
??????? Role role = list.get(i);?
??????? Set set = role.getModuleSet();?
??????? Iterator it = set.iterator();?
??????? while(it.hasNext()){?
??????? Module m = it.next();?
??????? Resource re = new Resource(m.getUrl(),role.getDescn());?
??????? rlist.add(re);?
??????? }?
??????? }?
return rlist;?
??????? }?
??? }?
??? public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {?
this.hibernateTemplate = hibernateTemplate;?
}?
private HibernateTemplate hibernateTemplate;?
}?
而從靈活性的角度考慮,把hql寫在配置文件中?
?
????????
???????? value="from com.lovo.po.Role order by ind">?
???????? ?
???????? ?
???????? ?
??? ?
????
??? 問題:系統只會在初始化的時候從數據庫中加載信息。無法識別數據庫中信息的改變。?
??? 解決:每個jsp頁面上重新內存?
??? 代碼:每個jsp頁面include如下代碼:?
首先導入spring security所需要的jar包?
spring-security-core-2.0.5.RELEASE.jar?
spring-security-core-tiger-2.0.5.RELEASE.jar?
一.配置過濾器?
在web.xml中定義如下過濾器?
? ?
??????? springSecurityFilterChain?
??????? org.springframework.web.filter.DelegatingFilterProxy?
??? ?
??? ?
??????? springSecurityFilterChain?
??????? ?
CREATE TABLE `t_account` (?
? `id` int(11) NOT NULL,?
? `username` varchar(255) default NULL,?
? `password` varchar(255) default NULL,?
? `enabled` int default NULL, ?
? PRIMARY KEY? (`id`)?
??? ) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
??? ?
??? CREATE TABLE `t_role` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL, ?
? `descn` varchar(255) default NULL, ?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_account_role` (?
? `a_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`a_id`,`r_id`),?
? KEY `FK1C2BC9332D31C656` (`r_id`),?
? KEY `FK1C2BC93371CCC630` (`a_id`),?
? CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`),?
? CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
當用戶登錄時,spring security首先判斷用戶是否可以登錄。用戶登錄后spring security獲得該用戶的?
所有權限以判斷用戶是否可以訪問資源。?
spring配置文件中定義?
?
???????
??????? users-by-username-query="select username,password,enabled from t_account where username=?"?
??????? authorities-by-username-query="select r.descn from t_account_role ar join?
???????? t_account a on ar.a_id=a.id join t_role r on ar.r_id=r.id where a.username=?"/>?
??? ?
????
??? users-by-username-query:根據用戶名查找用戶?
??? authorities-by-username-query:根據用戶名查找這個用戶所有的角色名,將用戶訪問的URL地址和?
??? 查詢結果與標簽進行匹配。?
??? 匹配成功就允許訪問,否則就返回到提示頁面。?
????
??? 在標簽中添加登錄頁面等信息?
??? ?
??? ? ?
??????? ?
??????? CREATE TABLE `t_account` (?
? `id` int(11) NOT NULL,?
? `username` varchar(255) default NULL,?
? `password` varchar(255) default NULL,?
? `enabled` int default NULL, ?
? PRIMARY KEY? (`id`)?
??? ) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
??? ?
??? CREATE TABLE `t_role` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL, ?
? `descn` varchar(255) default NULL, ?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_account_role` (?
? `a_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`a_id`,`r_id`),?
? KEY `FK1C2BC9332D31C656` (`r_id`),?
? KEY `FK1C2BC93371CCC630` (`a_id`),?
? CONSTRAINT `FK1C2BC93384B0A30E` FOREIGN KEY (`a_id`) REFERENCES `t_account` (`id`),?
? CONSTRAINT `FK1C2BC9332D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_module` (?
? `id` int(11) NOT NULL,?
? `name` varchar(255) default NULL,?
? `address` varchar(255) default NULL,?
? PRIMARY KEY? (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
CREATE TABLE `t_module_role` (?
? `m_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? PRIMARY KEY? (`m_id`,`r_id`),?
? KEY `FKA713071E2D31C656` (`r_id`),?
? KEY `FKA713071ED78C9071` (`m_id`),?
? CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`),?
? CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
??? insert into t_module values(1,'部門管理','/dept.jsp');?
??? insert into t_module values(2,'人員管理','/emp.jsp');?
????
??? insert into `t_module_role` values(1,1);?
??? insert into `t_module_role` values(1,2);?
??? insert into `t_module_role` values(2,1);?
????
1.在自定義的過濾器中獲取資源的URL地址和角色名以取代spring配置文件中原有的?
??? 過濾器代碼:?
import java.sql.ResultSet;?
import java.sql.SQLException;?
import java.util.LinkedHashMap;?
import java.util.List;?
import java.util.Map;?
import javax.sql.DataSource;?
import org.springframework.beans.factory.FactoryBean;?
import org.springframework.jdbc.core.support.JdbcDaoSupport;?
import org.springframework.jdbc.object.MappingSqlQuery;?
import org.springframework.security.ConfigAttributeDefinition;?
import org.springframework.security.ConfigAttributeEditor;?
import org.springframework.security.intercept.web.DefaultFilterInvocationDefinitionSource;?
import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;?
import org.springframework.security.intercept.web.RequestKey;?
import org.springframework.security.util.AntUrlPathMatcher;?
import org.springframework.security.util.UrlMatcher;?
public class JdbcFilterInvocationDefinitionSourceFactoryBean?
??? extends JdbcDaoSupport implements FactoryBean {?
??? private String resourceQuery;?
??? public boolean isSingleton() {?
??????? return true;?
??? }?
??? public Class getObjectType() {?
??????? return FilterInvocationDefinitionSource.class;?
??? }?
??? public Object getObject() {?
??????? return new DefaultFilterInvocationDefinitionSource(this?
??????????? .getUrlMatcher(), this.buildRequestMap());?
??? }?
??? protected Map findResources() {?
??????? ResourceMapping resourceMapping = new ResourceMapping(getDataSource(),?
??????????????? resourceQuery);?
??????? Map resourceMap = new LinkedHashMap();?
??????? for (Resource resource : (List) resourceMapping.execute()) {?
??????????? String url = resource.getUrl();?
??????????? String role = resource.getRole();?
??????????? if (resourceMap.containsKey(url)) {?
??????????????? String value = resourceMap.get(url);?
??????????????? resourceMap.put(url, value + "," + role);?
??????????? } else {?
??????????????? resourceMap.put(url, role);?
??????????? }?
??????? }?
??????? return resourceMap;?
??? }?
??? protected LinkedHashMap buildRequestMap() {?
??????? LinkedHashMap requestMap = null;?
??????? requestMap = new LinkedHashMap();?
??????? ConfigAttributeEditor editor = new ConfigAttributeEditor();?
??????? Map resourceMap = this.findResources();?
??????? for (Map.Entry entry : resourceMap.entrySet()) {?
??????????? RequestKey key = new RequestKey(entry.getKey(), null);?
??????????? editor.setAsText(entry.getValue());?
??????????? requestMap.put(key,?
??????????????? (ConfigAttributeDefinition) editor.getValue());?
??????? }?
??????? return requestMap;?
??? }?
??? protected UrlMatcher getUrlMatcher() {?
??????? return new AntUrlPathMatcher();?
??? }?
??? public void setResourceQuery(String resourceQuery) {?
??????? this.resourceQuery = resourceQuery;?
??? }?
??? private class Resource {?
??????? private String url;?
??????? private String role;?
??????? public Resource(String url, String role) {?
??????????? this.url = url;?
??????????? this.role = role;?
??????? }?
??????? public String getUrl() {?
??????????? return url;?
??????? }?
??????? public String getRole() {?
??????????? return role;?
??????? }?
??? }?
??? private class ResourceMapping extends MappingSqlQuery {?
??????? protected ResourceMapping(DataSource dataSource,?
??????????? String resourceQuery) {?
??????????? super(dataSource, resourceQuery);?
??????????? compile();?
??????? }?
??????? protected Object mapRow(ResultSet rs, int rownum)?
??????????? throws SQLException {?
??????????? String url = rs.getString(1);?
??????????? String role = rs.getString(2);?
??????????? Resource resource = new Resource(url, role);?
????????????
??????????? return resource;?
??????? }?
??? }?
}?
將自定義的過濾器放入到原有的spring security過濾器鏈中(在spring配置文件中配置)?
定義自定義過濾器(sql語句用于查詢資源的URL地址 如:/index.jsp 和角色名 如ROLE_USER)?
??????? class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean">?
??????? ?
??????? ??????????? select m.address,r.descn?
from t_module_role mr?
join t_module m on mr.m_id=m.id?
join t_role r on mr.r_id=r.id;?
??????? "/>?
??? ?
? 將自定義過濾器放入過濾器鏈中?
?
??????? class="org.springframework.security.intercept.web.FilterSecurityInterceptor" >?
??????? ?
??????? ?
??? ?
??? 注意:FilterSecurityInterceptor過濾器會向request中寫入一個標記,用于標記是否已經控制了當前請求,以避免對同一請求多次處理,導致第2個FilterSecurityInterceptor不會再次執行。?
??? 在中不需要再定義,如下:?
??? ?
???????
??????????????????? authentication-failure-url="/error.jsp"?
??????????????????? default-target-url="/index.jsp" />?
????????????????????
??? ?
??? 自定義的過濾器就從配置文件中讀取sql,查詢結果就是角色和資源,用戶登錄時就在session中保存了用戶的角色。?
??? 注意:intercept-url的先后順序,spring security使用第一個能匹配的intercept-url標簽進行權限控制。?
??? 現在intercept-url來源于數據庫,所以在sql查詢時注意角色和資源的順序。?
??? 建議在角色和資源的中間表中添加1個字段用于標識順序,(按從嚴到寬的順序)?
??? 表結構修改如下:?
??? ?
CREATE TABLE `t_module_role` (?
? `m_id` int(11) NOT NULL,?
? `r_id` int(11) NOT NULL,?
? `priority` int(11) default NULL, ?
? PRIMARY KEY? (`m_id`,`r_id`),?
? KEY `FKA713071E2D31C656` (`r_id`),?
? KEY `FKA713071ED78C9071` (`m_id`),?
? CONSTRAINT `FKA713071ED78C9071` FOREIGN KEY (`m_id`) REFERENCES `t_module` (`id`),?
? CONSTRAINT `FKA713071E2D31C656` FOREIGN KEY (`r_id`) REFERENCES `t_role` (`id`)?
) ENGINE=InnoDB DEFAULT CHARSET=utf8;?
數據如下:?
insert into t_account values(1,'zhangsan','123',1);?
insert into t_account values(2,'lisi','321',1);?
insert into t_role values(1,'系統管理員','ROLE_ADMIN');?
insert into t_role values(2,'普通用戶','ROLE_USER');?
insert into t_account_role values(1,2);?
??? insert into t_account_role values(2,1);?
????
??? insert into t_module values(1,'部門管理','/dept.jsp');?
??? insert into t_module values(2,'人員管理','/emp.jsp');?
????
??? insert into `t_module_role` values(1,1,3);?
??? insert into `t_module_role` values(1,2,2);?
??? insert into `t_module_role` values(2,1,1);?
????
??? 自定義過濾器修改如下:?
???
??????? class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean">?
??????? ?
??????? ??????????? select m.address,r.descn?
from t_module_role mr?
join t_module m on mr.m_id=m.id?
join t_role r on mr.r_id=r.id?
order by mr.priority?
??????? "/>?
??? ?
????
??? 如果持久層使用的是hibernate,那么只需要給自定義過濾器注入1個hibernateTemplate.?
??? 在自定義過濾器中就不需要再使用mapRow的方式。而是直接獲取url和角色名即可。?
??? 例如:?
??? public class ModuleFilter implements FactoryBean {?
private String resourceQuery;?
??? public boolean isSingleton() {?
??????? return true;?
??? }?
??? public Class getObjectType() {?
??????? return FilterInvocationDefinitionSource.class;?
??? }?
??? public Object getObject() {?
??????? return new DefaultFilterInvocationDefinitionSource(this?
??????????? .getUrlMatcher(), this.buildRequestMap());?
??? }?
??? protected Map findResources() {?
??????? ResourceMapping resourceMapping = new ResourceMapping();?
??????? Map resourceMap = new LinkedHashMap();?
??????? for (Resource resource : (List) resourceMapping.execute()) {?
??????????? String url = resource.getUrl();?
??????????? String role = resource.getRole();?
??????????? if (resourceMap.containsKey(url)) {?
??????????????? String value = resourceMap.get(url);?
??????????????? resourceMap.put(url, value + "," + role);?
??????????? } else {?
??????????????? resourceMap.put(url, role);?
??????????? }?
??????? }?
??????? return resourceMap;?
??? }?
??? protected LinkedHashMap buildRequestMap() {?
??????? LinkedHashMap requestMap = null;?
??????? requestMap = new LinkedHashMap();?
??????? ConfigAttributeEditor editor = new ConfigAttributeEditor();?
??????? Map resourceMap = this.findResources();?
??????? for (Map.Entry entry : resourceMap.entrySet()) {?
??????????? RequestKey key = new RequestKey(entry.getKey(), null);?
??????????? editor.setAsText(entry.getValue());?
??????????? requestMap.put(key,?
??????????????? (ConfigAttributeDefinition) editor.getValue());?
??????? }?
??????? return requestMap;?
??? }?
??? protected UrlMatcher getUrlMatcher() {?
??????? return new AntUrlPathMatcher();?
??? }?
??? public void setResourceQuery(String resourceQuery) {?
??????? this.resourceQuery = resourceQuery;?
??? }?
??? private class Resource {?
??????? private String url;?
??????? private String role;?
??????? public Resource(String url, String role) {?
??????????? this.url = url;?
??????????? this.role = role;?
??????? }?
??????? public String getUrl() {?
??????????? return url;?
??????? }?
??????? public String getRole() {?
??????????? return role;?
??????? }?
??? }?
??? private class ResourceMapping{?
??????? public List execute(){?
??????? List rlist = new ArrayList();?
??????? List list = hibernateTemplate.find(resourceQuery);?
??????? for(int i=0;i
??????? Role role = list.get(i);?
??????? Set set = role.getModuleSet();?
??????? Iterator it = set.iterator();?
??????? while(it.hasNext()){?
??????? Module m = it.next();?
??????? Resource re = new Resource(m.getUrl(),role.getDescn());?
??????? rlist.add(re);?
??????? }?
??????? }?
return rlist;?
??????? }?
??? }?
??? public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {?
this.hibernateTemplate = hibernateTemplate;?
}?
private HibernateTemplate hibernateTemplate;?
}?
而從靈活性的角度考慮,把hql寫在配置文件中?
?
????????
???????? value="from com.lovo.po.Role order by ind">?
???????? ?
???????? ?
???????? ?
??? ?
????
??? 問題:系統只會在初始化的時候從數據庫中加載信息。無法識別數據庫中信息的改變。?
??? 解決:每個jsp頁面上重新內存?
??? 代碼:每個jsp頁面include如下代碼:?
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
轉載于:https://www.cnblogs.com/ubuntuvim/p/4796542.html
總結
以上是生活随笔為你收集整理的springnbsp;security总结nbsp;太有用了!!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (王道408考研数据结构)第七章查找-第
- 下一篇: (王道408考研操作系统)第三章内存管理