springnbsp;security总结nbsp;太有用了!!
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;太有用了!!相关推荐
- 笔记本 数学计算机,Windows计算器大更新 这功能真是太有用了
近日, 微软推送了最新的Windows 10快速预览版19546系统更新,带来了几项新功能,包括Windows 计算器引入绘图模式,解决数学方程模式更丰富.现在版本的计算器只能进行简单的加减乘除,以及 ...
- SQL常见的一些面试题(太有用啦)
SQL常见的一些面试题(太有用啦) SQL常见面试题 1.用一条SQL 语句 查询出每门课都大于80 分的学生姓名 name kecheng fenshu 张三 语文 81 张三 数学 75 李四 语 ...
- 10分钟教会你看眼图,太有用了!!
10分钟教会你看眼图,太有用了!!-面包板社区 ●搜寻了不少资料,如果追溯历史,大约47年前,眼图就已经开始广泛应用.在1962年-2002的40年间,眼图的测量方法是基于采样示波器的传统方法,200 ...
- 判断java日期跨月_18 个 Java8 日期处理的实践,太有用了!
点击上方"Java技术前线",选择"置顶或者星标" 与你一起成长 作者 | 胖先森 来源 | juejin.im/post/5a795bad6fb9a0634f ...
- 高阶函数,太有用啦!
作者:chenhongdong 能来到这里就代表已经看过上一篇关于并不孤独的闭包文章了(没看不能来?当然--可以来),那么就不废话了,先来看下什么是高阶函数 高阶函数 函数可以作为参数传递 函数可以作 ...
- 18个Java8日期处理的实践,太有用了!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:juejin.im/post/5a795bad6fb9a06 ...
- 18 个 Java8 日期处理的实践,太有用了!
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 胖先森 来源 | juejin.im/post ...
- 六个经典的HTML5面试问题奉上,太有用啦!
随着移动互联网时代的到来,HTML5流行风盛行,HTML5开发工程师在人才市场中变得非常吃香.而2021年的今天,招聘网站上的HTML5开发工程师职位数量依旧庞大.那么求职者们怎样才能成功的面试上HT ...
- 超级浣熊的最近黑科技!?太有用了
前言 / Introduction 有社区的伙伴想开发 Cocos Creator 插件,但需要学习HTML.CSS以及各种Web前端库,对游戏开发程序员真的是太难了...... 社区大佬『超级浣熊』 ...
最新文章
- 小程序商城制作,轻松打造自己的会员系统
- php生成文字闪烁,如何用jquery实现闪烁文字效果
- 如何使git接受自签名证书?
- 软件工程-东北师大站-第十二次作业(PSP)
- ImportError: No module named sklearn.metrics
- linux shell跳板机,用shell开发跳板机
- java窗体容器坐标_Java的屏幕坐标是以像素为单位的,容器的左下角被确定为坐标的起点。...
- 判断url是否包含协议并添加协议(判断url是否包含协议,url添加协议头)
- GUID和INT两种数据类型做主键的比较
- cloc统计想项目行数
- HCIE理论-IPV6
- IOS面试题(收集整理)
- android父布局的右侧,相对布局(RelativeLayout)的控件运用
- COJ 0358 xjr考考你数据结构(根号3)线段树区间修改
- [11g](ALTER SYSTEM SUSPEND)Suspending and Resuming a Database
- .Net Core裁剪图片并存入数据库
- docker 搭建frp内网穿透以及frp详细使用
- 力扣题解:45. 跳跃游戏 II
- Magnetic Actuation Systems for Miniature Robots: A Review
- 信息系统项目管理师2019年上半年上午试题解析(一)