- 浏览: 821861 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (488)
- struts1 (4)
- spring (13)
- extjs (36)
- mysql (3)
- sqlserver (2)
- oracle (37)
- 杂谈 (11)
- 面试相关 (35)
- Java基础知识总结 (5)
- Java重要知识点 线程和io流知识点 (6)
- 服务器相关 (1)
- 生活 (1)
- jsp (7)
- servlet (2)
- junit (3)
- struts2 (9)
- 开发必备 (4)
- 使用开发工具总结的知识 (4)
- ibatis (12)
- ajax (2)
- dwr (2)
- jquery (1)
- 设计模式 (4)
- Lucene的学习 (5)
- 经验总结 (19)
- mysql全文搜索相关 (7)
- hibernate (33)
- Sphinx (1)
- log4j的总结 (1)
- 敏捷开发 (9)
- 持续集成 (15)
- UML使用总结 (1)
- Scrum (1)
- OO(面向对象编程) (1)
- struts1和struts2总结 (1)
- 数据库加密 (1)
- 多线程和Socket编程 (6)
- PowerDesigner (2)
- 权限相关 (1)
- ant应用总结 (4)
- 面试必知知识点总结 (6)
- io流与nio流总结 面试相关 (1)
- 敏捷管理工具的使用 (7)
- hsqldb相关 (1)
- svn源码相关 (2)
- debug调试技巧总结 (1)
- hibernate和ibatis对比相关 (6)
- eclipse mylyn 插件的使用总结 (2)
- fisheye使用总结 (2)
- java泛型总结 (1)
- ssh整合总结 (10)
- SpringSide的学习总结 (1)
- JPA学习总结 (2)
- RoR 总结 (2)
- 模型驱动 总结 (1)
- Oracle SQL优化技巧 (4)
- 数据库相关资料 (1)
- oracle练习相关 (4)
- PowerDesigner 使用总结 (2)
- Struts实现国际化相关 (2)
- 权限框架 Spring Security (1)
- freemarker使用总结 (1)
- jsp servlet总结相关 (3)
- Java NIO总结 (1)
- 自己学习必须 (3)
- 蝴蝶容器相关 (2)
- eclipse插件的使用 (1)
- myeclipse的使用 (1)
- flex相关 (1)
- javaeye重生后总结的知识点 (2)
- 公司学习总结 (3)
- JAXB 相关 (1)
- ECSide (1)
- EdoJs 企业ajax框架 (1)
- RSA加密算法 (1)
- jbpm相关 (1)
- JMF原理 (1)
- MyEclipse使用总结 (1)
- Funsion Charts 相关总结 (3)
- 常用知识2011 (2)
- Flex与Java整合 (1)
- IBM WebSphere相关 (1)
- jQuery使用技巧 (2)
- 2011年面试相关知识点总结 (2)
- sqlserver开发相关 (8)
- eclipse 打jar相关 (2)
- Oracle/Mysql/SqlServer比较 (1)
- WebService Axis1.4开发相关 (4)
- 进制数的转换 总结 (1)
- WebService Axis2.0开发相关 (0)
- iteye Struts2 Spring Hibernate整合相关 (3)
- iteye osgi资料相关总结 (1)
- iteye ifos相关相关 (1)
- iteye 国际化相关 (1)
- iteye Hibernate缓存机制 (4)
- iteye Struts2 总结 (1)
- iteye Struts标签总结 (0)
- iteye web配置文件大全 (6)
- iteye Efs 框架总结 (1)
- iteye sql优化 (2)
- iteye 大数据量高并发的数据库优化 (1)
- iteye 开发相关 (1)
- iteye s1sh 和 s2sh整合中的问题以及解决 (1)
- iteye s1sh整合实例 (1)
- iteye s2sh整合实例 (1)
- iteye 面试相关 基础篇 (1)
- iteye Android相关 (1)
- iteye 面试相关 Web篇 (1)
- iteye Sql Server相关 (0)
- iteye struts1与struts2比较 (1)
- iteye jquery 和Struts2 (0)
- iteye struts2与其他插件整合 (0)
- iteye jquery 开发相关 (1)
- iteye eclipse结合spket(Ext,Jquery)开发相关 (0)
- iteye myeclipse 使用技巧相关 (0)
- iteye Memcached 缓存系统相关 (0)
- iteye 常用软件相关 (0)
- iteye 最新技术预览 AjaxSwing (0)
- iteye struts上传下载相关 (0)
- iteye 新技术相关 (0)
- test (0)
- iteye 开发Java游戏相关 (0)
- iteye Java反编译 (0)
- iteye XML解析相关 (0)
- iteye 压缩ZIP相关 (0)
- iteye 面试相关 (0)
- iteye Android开发相关 (4)
- csdn (0)
- e-inoc (0)
- iteye http错误码对应说明 (0)
- iteye 面试扩展知识点 (0)
- iteye oracle面试相关 存储过程,触发器,游标等 (0)
- iteye english study (0)
- iteye starflow工作流引擎 (0)
- iteye IBM WebSphere Application Server Toolkit使用相关 (0)
- iteye spring3 (0)
- iteye mybatis (0)
- iteye js技巧总结 (0)
- iteye SEO优化相关 (2)
- iteye QUI网页界面集成框架 (1)
- iteye AjaxAnywhere (1)
- iteye Nutz相关 (1)
- iteye ibatis技巧 (0)
- iteye dwz (0)
- 128个ajax/javascript框架 (0)
- iteye 2012 Java Swing教程 (1)
- iteye 码头集装箱相关 (1)
- iteye swing (2)
- 兼职工作 (0)
- 2012 新总结的面试相关知识点 常用知识点 (1)
- 淘宝网店相关 (0)
- oracle 常用函数 2012新总结 (1)
- 我的时尚潮流屋 (0)
- 2012 年 面试新总结知识 (1)
- 技巧 (1)
- 2013总结 (1)
- 2015工作相关 (3)
- springmvc (5)
- EasyPR-Java (1)
- java (2)
- editplus 4.0 注册码 (1)
- android (1)
- oracle连接数据库相关 (1)
- 编程资料总结 (2)
- 20160808 (1)
- visio 2013 (1)
最新评论
-
drew926:
泛型的类型参数可以有多个?这是java哪个版本支持的?
java泛型总结 -
listenan:
赞!非常感谢。
Scrum总结 -
cwscwj:
写的很深刻,谢谢,看了一遍,过段时间打算再看一遍。
Scrum总结 -
hwedwin:
w
Struts 2中的OGNL\EL的使用总结 -
lanni2460:
不错 很好 支持……
sqlserver三个驱动包下载
Spring下的权限框架 spring security总结
spring security总结 首先导入spring security所需要的jar包 spring-security-core-2.0.5.RELEASE.jar spring-security-core-tiger-2.0.5.RELEASE.jar 一.配置过滤器 在web.xml中定义如下过滤器 <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 二.在spring配置文件中添加security的命名空间 <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> 三.在spring配置文中中定义需要保护的资源 <http auto-config='true'> <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> <intercept-url pattern="/**" access="ROLE_USER" /> </http> 注意intercept-url的先后顺序,spring security使用第一个能匹配的intercept-url标签进行权限控制。 四.使用数据库获取用户权限 <!-- 数据源 --> <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver"></beans:property> <beans:property name="url" value="jdbc:mysql://localhost:3306/sp"></beans:property> <beans:property name="username" value="root"></beans:property> <beans:property name="password" value="root"></beans:property> </beans:bean> <!-- 定义用户的权限根据注入的数据源获得 --> <authentication-provider> <jdbc-user-service data-source-ref="dataSource"/> </authentication-provider> 定义权限管理模块的表结构(mysql数据库) alter table `t_account_role` drop foreign key `FK1C2BC93384B0A30E`; alter table `t_account_role` drop foreign key `FK1C2BC9332D31C656`; drop table if exists `t_account_role`; drop table if exists `t_account`; drop table if exists `t_role`; /* 用户表 */ CREATE TABLE `t_account` ( `id` int(11) NOT NULL, `username` varchar(255) default NULL, `password` varchar(255) default NULL, `enabled` int default NULL, /* 用户是否禁用 0:禁用 非0:可用*/ 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, /* 角色在spring配置文件中的名字 如ROLE_ADMIN,ROLE_USER*/ 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配置文件中定义 <authentication-provider> <jdbc-user-service data-source-ref="dataSource" 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=?"/> </authentication-provider> users-by-username-query:根据用户名查找用户 authorities-by-username-query:根据用户名查找这个用户所有的角色名,将用户访问的URL地址和 查询结果与<intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />标签进行匹配。 匹配成功就允许访问,否则就返回到提示页面。 在<http>标签中添加登录页面等信息 <http auto-config='true'> <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page="/login.jsp" authentication-failure-url="/error.jsp" default-target-url="/index.jsp" /> </http> <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>让没有登录的用户也可以访问登录页面 <form-login login-page="/login.jsp" authentication-failure-url="/error.jsp" default-target-url="/index.jsp" /> login-page:当用户登录时显示自定义登录页面 authentication-failure-url:登录失败时跳转到哪个页面 default-target-url:登录成功后跳转到哪个页面 注意:users-by-username-query指定的查询,必须至少按顺序返回3列,列名必须是 username,password,enabled authorities-by-username-query指定的查询,必须至少按顺序返回2列,第一列列名必须是username 第2列必须是权限的名字,与<intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />中的 access匹配。 不能使用select * 完成的配置文件: <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"> <!-- 数据源 --> <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver"></beans:property> <beans:property name="url" value="jdbc:mysql://localhost:3306/sp"></beans:property> <beans:property name="username" value="root"></beans:property> <beans:property name="password" value="root"></beans:property> </beans:bean> <http auto-config='true'> <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> <intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN" /> <form-login login-page="/login.jsp" authentication-failure-url="/error.jsp" default-target-url="/index.jsp" /> </http> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,enabled from t_account where username=?" authorities-by-username-query="select a.username,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=?"/> </authentication-provider> </beans:beans> 登录页面 <form action="${pageContext.request.contextPath}/j_spring_security_check" method="post"> 用户: <input type="text" name="j_username" value="${SPRING_SECURITY_LAST_USERNAME}"/><br /> 密码: <input type="password" name="j_password"/><br /> <input type="checkbox" name="_spring_security_remember_me" />两周之内不必登陆<br /> <input type="submit" value="登陆"/><input type="reset" value="重置"/> </form> 页面中输入控件的name属性和form的action地址必须符合spring security的规定 登录失败页面 ${SPRING_SECURITY_LAST_EXCEPTION.message} 获取spring生成的异常 将资源信息放入数据库中 表结构 /* 用户表 */ CREATE TABLE `t_account` ( `id` int(11) NOT NULL, `username` varchar(255) default NULL, `password` varchar(255) default NULL, `enabled` int default NULL, /* 用户是否禁用 0:禁用 非0:可用*/ 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, /* 角色在spring配置文件中的名字 如ROLE_ADMIN,ROLE_USER*/ 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配置文件中原有的<intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/> 过滤器代码: 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<String, String> findResources() { ResourceMapping resourceMapping = new ResourceMapping(getDataSource(), resourceQuery); Map<String, String> resourceMap = new LinkedHashMap<String, String>(); for (Resource resource : (List<Resource>) 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<RequestKey, ConfigAttributeDefinition> buildRequestMap() { LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap = null; requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); Map<String, String> resourceMap = this.findResources(); for (Map.Entry<String, String> 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) <beans:bean id="filterInvocationDefinitionSource" class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean"> <beans:property name="dataSource" ref="dataSource"/> <beans:property name="resourceQuery" value=" 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; "/> </beans:bean> 将自定义过滤器放入过滤器链中 <beans:bean id="filterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor" autowire="byType"> <custom-filter before="FILTER_SECURITY_INTERCEPTOR"/> <beans:property name="objectDefinitionSource" ref="filterInvocationDefinitionSource" /> </beans:bean> 注意:FilterSecurityInterceptor过滤器会向request中写入一个标记,用于标记是否已经控制了当前请求,以避免对同一请求多次处理,导致第2个FilterSecurityInterceptor不会再次执行。 在<http>中不需要再定义<intercept-url>,如下: <http auto-config='true'> <form-login login-page="/login.jsp" authentication-failure-url="/error.jsp" default-target-url="/index.jsp" /> </http> 自定义的过滤器就从配置文件中读取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); 自定义过滤器修改如下: <beans:bean id="filterInvocationDefinitionSource" class="com.lovo.JdbcFilterInvocationDefinitionSourceFactoryBean"> <beans:property name="dataSource" ref="dataSource"/> <beans:property name="resourceQuery" value=" 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 "/> </beans:bean> 如果持久层使用的是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<String, String> findResources() { ResourceMapping resourceMapping = new ResourceMapping(); Map<String, String> resourceMap = new LinkedHashMap<String, String>(); for (Resource resource : (List<Resource>) 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<RequestKey, ConfigAttributeDefinition> buildRequestMap() { LinkedHashMap<RequestKey, ConfigAttributeDefinition> requestMap = null; requestMap = new LinkedHashMap<RequestKey, ConfigAttributeDefinition>(); ConfigAttributeEditor editor = new ConfigAttributeEditor(); Map<String, String> resourceMap = this.findResources(); for (Map.Entry<String, String> 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<Resource> execute(){ List<Resource> rlist = new ArrayList<Resource>(); List<Role> list = hibernateTemplate.find(resourceQuery); for(int i=0;i<list.size();i++){ Role role = list.get(i); Set<Module> set = role.getModuleSet(); Iterator<Module> 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写在配置文件中 <beans:bean id="moduleFilter" class="com.lovo.ModuleFilter"> <beans:property name="resourceQuery" value="from com.lovo.po.Role order by ind"> </beans:property> <beans:property name="hibernateTemplate" ref="hibernateTemplate"> </beans:property> </beans:bean> 问题:系统只会在初始化的时候从数据库中加载信息。无法识别数据库中信息的改变。 解决:每个jsp页面上重新内存 代码:每个jsp页面include如下代码: <%@page import="org.springframework.context.ApplicationContext"%> <%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%> <%@page import="org.springframework.beans.factory.FactoryBean"%> <%@page import="org.springframework.security.intercept.web.FilterSecurityInterceptor"%> <%@page import="org.springframework.security.intercept.web.FilterInvocationDefinitionSource"%> <% ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application); FactoryBean factoryBean = (FactoryBean) ctx.getBean("&自定义过滤器的id"); FilterInvocationDefinitionSource fids = (FilterInvocationDefinitionSource) factoryBean.getObject(); FilterSecurityInterceptor filter = (FilterSecurityInterceptor) ctx.getBean("filterSecurityInterceptor"); filter.setObjectDefinitionSource(fids); %> 控制用户信息 用户密码MD5加密: <authentication-provider> <password-encoder hash="md5"/> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,enabled from t_account where username=?" authorities-by-username-query="select a.username,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=?"/> </authentication-provider> 盐值加密 <authentication-provider> <password-encoder hash="md5"> <salt-source user-property="username"/> </password-encoder> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,enabled from t_account where username=?" authorities-by-username-query="select a.username,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=?"/> </authentication-provider> 用户信息缓存,使用spring内置的ehCache实现 <beans:bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"></beans:bean> <beans:bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <beans:property name="cacheManager" ref="cacheManager"></beans:property> <beans:property name="cacheName" value="userCache"></beans:property> </beans:bean> <beans:bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache"> <beans:property name="cache" ref="userEhCache"></beans:property> </beans:bean> 在src目录下新建ehcache.xml <ehcache> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="1000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="userCache" maxElementsInMemory="100" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="3600" overflowToDisk="true" /> </ehcache> 在程序中获取用户信息 UserDetails ud = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String name = ud.getUsername(); String pwd = ud.getPassword(); GrantedAuthority[] ga = ud.getAuthorities(); System.out.println(name + "," + pwd); for(GrantedAuthority g : ga){ System.out.println(g.getAuthority()); } 自定义访问拒绝页面 <http auto-config='true' access-denied-page="/error.jsp"> 访问用户以带参形式访问 在资源URL地址后加* 如 insert into t_module values(1,'部门管理','/dept.jsp*'); insert into t_module values(2,'人员管理','/emp.jsp*'); 自定义用户接口实现 由于将sql写在配置文件中只适用于小型系统,而且不灵活,在大型系统或实体关系复杂时需要自定义用户实现的接口。 自定义用户实现需要实现2个接口。 UserDetails:实体类需要实现的接口。 UserDetailsService:实体管理类需要实现的接口。 配置: <!-- 实体管理类 --> <beans:bean id="userManager" class="com.lovo.UserManager"></beans:bean> <authentication-provider user-service-ref="userManager"> <!-- <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,enabled from t_account where username=?" authorities-by-username-query="select a.username,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=?"/> --> </authentication-provider> 原有的通过固定sql语句的获取方式可以抛弃,改为使用user-service-ref属性注入的bean来实现对用户及用户所 拥有的资源的查找。 用户注销 注销功能由过滤器org.springframework.security.ui.logout.LogoutFilter负责完成。 <a href="${pageContext.request.contextPath}/j_spring_security_logout">注销</a> 被注销的用户就是当前session中保存的用户,注销后页面自动重定向到default-target-url所指定的页面 spring security过滤器体系 spring security的一系列功能都是由一串过滤器来完成的。在spring配置文件中配置的<http>标签实际上就是 起到默认的过滤器进行声明和配置的作用。 管理会话 当项目中要求不能使用同一个账号同时登陆,按以下步骤实施 1.web.xml添加1个监听器 <listener> <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class> </listener> 2.spring配置文件中的<http>标签添加子标签<concurrent-session-control/> <http auto-config='true' access-denied-page="/noview.jsp"> <form-login login-page="/login.jsp" authentication-failure-url="/error.jsp" default-target-url="/index.jsp"/> <concurrent-session-control/> </http> <concurrent-session-control/>会产生1个 org.springframework.security.concurrent.ConcurrentSessionFilter 并放在过滤器链的最前面。 默认情况下,使用同一账号后登陆的用户会踢出先登陆的用户。 如果想禁止第2个用户登录,则设置 <concurrent-session-control exception-if-maximum-exceeded="true"/> 对方法级的权限控制 1.添加依赖包 cglib-nodep-2.1_3.jar aspectjweaver.jar aspectjrt.jar 2.利用<global-method-security>设置需要保护的方法及可以调用的权限 <global-method-security> <protect-pointcut access="ROLE_ADMIN,ROLE_USER" expression="execution(* com.lovo.bo.AccountBo.get*(..))"/> <protect-pointcut access="ROLE_ADMIN" expression="execution(* com.lovo.bo.AccountBo.create*(..))"/> </global-method-security> 利用注解同样可以实现方法级的保护 需要spring-security-core-tiger.jar包 启用注解保护 <global-method-security secured-annotations="enabled"/> @Secured({"ROLE_ADMIN","ROLE_USER"}) public void getOneAccount(); 拥护ROLE_ADMIN或ROLE_USER权限的用户可以调用该方法 SecurityContext安全上下文 SecurityContext securityContext = SecurityContextHolder.getContext(); SecurityContext中保存着实现了Authentication 接口的对象,如果用户尚未通过 认证,那么SecurityContext.getAuthenticaiton()方法就会返回null。 注意,如果使用了匿名用户,SecurityContext.getAuthenticaiton()返回的不是null. 只有在未启用过滤器链的情况下,SecurityContext.getAuthenticaiton()才返回空。 验证管理器 验证管理器用来识别用户的身份。使用命名空间会自动注册一个验证管理器的bean. 是org.springframework.security.providers.ProviderManager类的一个对象。 如果要在其他的bean中要引用这个验证管理器,则给这个验证管理器取一个别名。 <authentication-manager alias="authenticationManager"/> 如果要采用其他的类来完成验证管理器的功能,可以使用以下标签 <beans:bean id="abc" class="org.springframework.security.providers.dao.DaoAuthenticationProvider"> <custom-authentication-provider/> </beans:bean> 访问决策管理器 当使用命名空间配置时,默认的AccessDecisionManager实例会自动注册。 默认的策略是使用一个AffirmativeBased作为AccessDecisionManager(访问决策管理器),投票者是RoleVoter 和 AuthenticatedVote <global-method-security secured-annotations="enabled" access-decision-manager-ref="accessDecisionManager"> </global-method-security> 利用访问决策管理器对方法进行保护 <beans:bean id="filterSecurityInterceptor" class="org.springframework.security.intercept.web.FilterSecurityInterceptor" autowire="byType"> <custom-filter before="FILTER_SECURITY_INTERCEPTOR"/> <beans:property name="objectDefinitionSource" ref="moduleFilter" /> <beans:property name="accessDecisionManager" ref="accessDecisionManager"></beans:property> </beans:bean> 向过滤器注入访问决策管理器 不管是MethodSecurityInterceptor还是FilterSecurityInterceptor都使用 authenticationManager和accessDecisionManager属性用于验证用户,并且都是通过使用 objectDefinitionSource属性来定义受保护的资源。不同的是过滤器安全拦截器将URL资源与权限关联,而方法安全拦截器将业务方法与权限关联。 objectDefinitionSource属性需要注入的就是 org.springframework.security.intercept.ObjectDefinitionSource这个接口的实现类。 该接口中有一个方法是: ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException; 参数实际类型是org.springframework.security.intercept.web.FilterInvocation 这个方法用于获取保护资源对应的权限信息,返回一个ConfigAttributeDefinition对象。 ConfigAttributeDefinition对象内部维护1个列表,安全拦截器就通过调用getAttributes方法来获取 ConfigAttributeDefinition对象,并将该对象和当前用户拥有的Authentication对象传递给 accessDecisionManager(访问决策管理器) 访问决策管理器在将其传递给具体实现类维护的投票者,这些投票者从ConfigAttributeDefinition对象中获取这个存放了访问保护资源需要的权限信息的列表,然后遍历这个列表并与 Authentication对象中GrantedAuthority[]数据中的用户权限信息进行匹配,如果匹配成功,投票者就会投赞成票,否则就投反对票,最后访问决策管理器来统计这些投票决定用户是否能访问该资源。 FilterInvocationDefinitionSource接口和MethodDefinitionSource接口继承自 ObjectDefinitionSource接口,并提供了2个默认实现类用以从配置文件读取权限信息。 是DefaultFilterInvocationDefinitionSource和 DelegatingMethodDefinitionSource两个类,如果需要从其他数据来源读取则需要实现 FilterInvocationDefinitionSource接口和MethodDefinitionSource接口。 自定义的过滤器必须注入 objectDefinitionSource,accessDecisionManager,authenticationManager3个属性。 FilterInvocationDefinitionSource接口getAttributes实现思路 1.获取客户端访问的url地址。 2.将该url地址和数据库中存储的url地址匹配,找到所有有权访问该地址的权限(角色)名字。 3.把所有的权限名利用ConfigAttributeEditor类封装成ConfigAttributeDefinition对象 简单例子: public class MyFilter extends HibernateDaoSupport implements FilterInvocationDefinitionSource,FactoryBean{ //保存权限信息(能够访问当前资源的角色名) private List<String> roleNameList = new ArrayList<String>(); public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { FilterInvocation fi = (FilterInvocation)object; String requeatUrl = fi.getRequestUrl(); //获取客户端访问的url地址 requeatUrl = requeatUrl.toLowerCase(); //将url地址全部转换成小写 if(requeatUrl.indexOf("?") != -1){ //过滤请求参数 requeatUrl = requeatUrl.substring(0,requeatUrl.indexOf("?")); } //在数据库中查找能够访问此url地址的角色 List<Module> list = this.getHibernateTemplate().find("from com.lovo.po.Module where url like ?",requeatUrl+"%"); if(list.size() <= 0){ return null; } String s = ""; Module module = (Module)list.get(0); Set<Role> set = module.getRoleSet(); roleNameList.clear(); for(Role role : set){ roleNameList.add(role.getDescn()); s += role.getDescn() + ","; } s = s.substring(0,(s.length() - 1)); //将所有的角色名(ROLE_开头)拼接为一个字符串。 ConfigAttributeEditor editer = new ConfigAttributeEditor(); editer.setAsText(s); return (ConfigAttributeDefinition) editer.getValue(); //将包含所有角色名(ROLE_开头)的字符串转换为ConfigAttributeDefinition对象。 } public Collection getConfigAttributeDefinitions() { return Collections.unmodifiableCollection(this.roleNameList); } public boolean supports(Class clazz) { return FilterInvocation.class.isAssignableFrom(clazz); } public Object getObject() throws Exception { return this; } public Class getObjectType() { return FilterInvocationDefinitionSource.class; } public boolean isSingleton() { // TODO Auto-generated method stub return true; } } 方法保护的原理是通过aop来实现的。 <aop:config> <aop:pointcut expression="execution(* com.lovo.bo.face.*.*(..))" id="me"/> <aop:advisor advice-ref="methodSecurityInterceptor" pointcut-ref="me"/> </aop:config> 通知是1个实现了MethodSecurityInterceptor接口的类 methodSecurityInterceptor是spring中的一个类 <beans:bean id="methodSecurityInterceptor" class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor"> <beans:property name="objectDefinitionSource" ref="methodFilter" /> <beans:property name="accessDecisionManager" ref="accessDecisionManager"></beans:property> <beans:property name="authenticationManager" ref="authenticationManager"></beans:property> </beans:bean> accessDecisionManager属性注入访问决策管理器,authenticationManager属性注入验证管理器。 objectDefinitionSource属性注入1个实现了MethodDefinitionSource接口的类。 <beans:bean id="methodFilter" class="com.lovo.method.MethodFilter"> <beans:property name="hibernateTemplate" ref="hibernateTemplate"></beans:property> </beans:bean> 这个类的作用是根据用户调用的方法,找到相应的角色, public class MethodFilter extends HibernateDaoSupport implements MethodDefinitionSource{ private List<String> roleList = new ArrayList<String>(); public ConfigAttributeDefinition getAttributes(Method method, Class targetClass) { return null; } public ConfigAttributeDefinition getAttributes(Object object) throws IllegalArgumentException { ConfigAttributeEditor editor = new ConfigAttributeEditor(); String s = ""; ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation)object; String methodName = rmi.getThis().getClass().getName() + "." + rmi.getMethod().getName(); System.out.println(methodName); List<Module> list = this.getHibernateTemplate().find("from com.lovo.po.Module where url like ?",methodName); if(list.size() == 0){ return null; } roleList.clear(); for(int i=0;i<list.size();i++){ Module module = list.get(i); Set<Role> roleSet = module.getRoleSet(); Iterator<Role> it = roleSet.iterator(); while(it.hasNext()){ Role role = it.next(); s += role.getDescn() + ","; roleList.add(role.getDescn()); } } s = s.substring(0,(s.length() - 1)); editor.setAsText(s); editor.getValue(); return (ConfigAttributeDefinition) editor.getValue(); } public Collection getConfigAttributeDefinitions() { return roleList; } public boolean supports(Class clazz) { return true; } }
相关推荐
总结,Spring Security 是一个功能丰富的安全框架,可以帮助开发者构建安全的Web应用程序,提供全面的认证、授权和会话管理功能。通过深入理解并灵活运用Spring Security,你可以构建出符合业务需求且安全性高的应用...
在这个“springboot springsecurity动态权限控制”的主题中,我们将深入探讨如何在Spring Boot项目中集成Spring Security,实现动态权限控制,让菜单权限的管理更加灵活和高效。 首先,我们需要理解Spring Security...
spring security权限框架简要介绍, 可结合文档和官网编写个小Demo
总结,SpringSecurity是一个功能强大的安全框架,它为开发者提供了安全Web应用的全套解决方案。通过理解并熟练运用其核心概念和组件,我们可以构建出安全、健壮的应用程序。在学习过程中,分析提供的源代码和示例将...
Spring Security 是一个功能强大的安全框架,可以为基于Java的应用程序提供认证(Authentication)、授权(Authorization)等功能,同时提供了丰富的配置选项来满足不同的应用场景需求。 #### 二、传统Web应用安全开发...
而Spring Security 则是 Java 开发中广泛使用的安全框架,用于实现认证和授权。当我们将这两者结合时,我们可以创建一个强大的统一登录认证鉴权系统。 首先,让我们深入了解Spring Cloud Gateway。这是一个基于...
SpringSecurity是Java领域中一个强大的安全框架,专为Web应用和企业级应用提供全面的安全解决方案。它涵盖了身份验证、授权、访问控制等多个方面,确保只有合法的用户才能访问特定的资源和服务。在深入探讨Spring...
**Spring Security 用户权限项目概述** Spring Security 是一个强大的安全框架,专为 Java 应用程序设计,用于处理身份验证和授权。在这个项目中,它被用来实现用户权限管理,确保只有授权的用户才能访问特定的资源...
Spring Security 是一个强大的且高度可定制的 Java 安全框架,用于解决 Web 应用程序的安全问题。这个框架提供了一套全面的解决方案,包括身份验证、授权、会话管理以及跨站请求伪造(CSRF)防护等核心功能。在本文...
这个“Spring Security 权限控制中文API”很可能是对Spring Security框架的中文文档或指南,帮助开发者理解和使用权限控制功能。 Spring Security的核心在于保护资源、进行身份验证(Authentication)和授权...
这个"SpringSecurity安全框架基础Demo"旨在帮助开发者快速理解和实践Spring Security的核心功能。 **1. 用户认证** 在Spring Security中,用户认证主要由Authentication对象负责。当用户尝试访问受保护的资源时,...
基于Spring Boot框架的Spring Security项目 项目简介 本项目是一个基于Spring Boot框架的Spring Security项目,涵盖了Spring Boot、Spring Security、Spring Cloud等多个技术栈的应用。项目主要功能包括用户认证...
Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,专为Java应用程序设计。它在Spring生态系统中扮演着核心安全组件的角色,使得开发者能够轻松地实现安全性需求,包括用户认证、授权、会话管理...
Spring Security是一个功能强大且广泛应用的Java安全框架,它提供了许多功能,包括身份验证、授权、加密等。其中,权限控制是Spring Security的一个重要组件,它允许开发者根据用户角色和权限来控制访问不同的资源...
Spring Security 是一个基于 Java 的安全框架,旨在提供身份验证、授权和访问控制等功能。下面是 Spring Security 的主要知识点: 一、身份验证(Authentication) 身份验证是指对用户身份的验证,以确保用户的...
Spring Security 是一个强大的安全框架,用于为Java应用提供安全控制。在传统的权限管理中,权限配置通常硬编码在应用程序中,这使得权限调整变得困难,每次变动都需要重新部署应用。然而,通过动态授权,我们可以将...
Spring Security是一个功能强大、高度定制的安全框架,它专门用于为基于Spring的应用程序提供安全性解决方案。Spring Security架构的设计初衷是为了解决认证和授权的需求,确保应用程序的安全性。它提供了全面的安全...
在版本2.5时,Spring Security已经是一个成熟且功能丰富的安全框架,为开发者提供了一套强大的工具来管理用户的登录、权限控制以及会话管理。 在"spring security2.5 jar"中,包含了Spring Security框架的核心类和...
Spring Security 是一个强大的安全框架,用于为Java应用提供身份验证和授权服务。在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、...