PureJS (6.4):利用 proxy 对象实现权限控制和数据校验
利用上一篇文章提到的 proxy 对象,我们还可以实现更多实用的功能。比如本文将探讨的权限控制和数据校验。
权限控制的思路是截获对 page.* 和 api.* 的调用,并利用 session 中记录的用户角色信息进行权限检查;
数据校验还将用到之前的客户端与服务器端共用代码的功能,对数据进行双重检查,以防恶意攻击。
接下来就让我们看看具体的实现吧。
权限控制
这里以对 page.* 的调用为例。基本思路是:
1. 通过正则表达式 /^page./ 和 /^api./ 匹配需要拦截的方法调用
2. 获取参数中的 req (ServletHttpRequest)
3. 获取 session 中的用户角色
4. 如果用户的角色是 admin ,则显示相应页面;否则显示登陆页面
(function() {
var log = pure.log("proxy.security");
proxy.security = { priority: 80 };
// 对 page.* 的调用进行权限控制
proxy.security.page = {
priority: 100,
expr: /^page./,
func: function(name, method, args) {
// 获取方法的第二个参数,即 req
var req = args[1];
// 读取 session 中的role。返回值是 java.lang.String
// 加上空字符串转为 JavaScript 中的 String
var role = req.session.getAttribute("user.role") + "";
// 如果角色是 "admin",则显示相应页面
// 否则,显示登录页面
if (role === "admin") {
return this[method].apply(this, args);
} else {
log.info("Redirect to login page.");
return pure.render("login");
}
}
}
// 利用类似的方法对 api.* 的调用进行权限控制,略
proxy.security.api = { ... }
}());
简单起见,这里仅包含了 admin 一种角色。
启动 mongod 和 PureJS 工程(见附件),输入
http://localhost:8080/,将显示登录页面,在控制台输出(或日志)中也可以看到“Redirect to login page.”的提示。
输入用户名和密码并点击 Sign in 之后,将显示用户列表。
数据校验
在介绍服务器端利用 JQuery 进行页面渲染时,我们提到了服务器端与客户端共用代码的实现(
http://xxing22657-yahoo-com-cn.iteye.com/blog/1113665)。
现在在数据校验功能的实现中我们将再次利用这个功能。
首先编写在服务器端和浏览器中共用的 validator 对象:
webapp/js/both/validator.js
validator = {};
// 校验异常信息
validator.USER_INVALID = "Invalid user data.";
validator.USER_NAME_EMPTY = "Name cannot be empty.";
validator.USER_NAME_TOO_LONG = "Name cannot be longer than 50.";
validator.USER_DESC_EMPTY = "Description cannot be empty.";
validator.USER_DESC_TOO_LONG = "Description cannot be longer than 50.";
// 检查 user 对象的方法
validator.validateUser = function(user) {
// 参数类型错误,可能是恶意攻击
if (typeof user.name !== "string"
|| typeof user.desc !== "string") {
return { success: false, error: validator.USER_INVALID };
}
// name 为空
if (!user.name) {
return { success: false, error: validator.USER_NAME_EMPTY };
}
// name 过长
if (user.name.length > 50) {
return { success: false, error: validator.USER_NAME_TOO_LONG };
}
// desc 为空
if (!user.desc) {
return { success: false, error: validator.USER_DESC_EMPTY };
}
// desc 过长
if (user.desc.length > 50) {
return { success: false, error: validator.USER_DESC_TOO_LONG };
}
// 提取 name 和 desc;因为对象中可能还有其他不需要的属性
var data = { name: user.name, desc: user.desc }
return { success: true, data: data };
}
这段代码在服务器端的 proxy.validation.saveUser 和 浏览器端的 save(...) 中被用到。
客户端的校验是为了给用户更快的反馈,服务器端的校验是为了避免恶意攻击。
代码实现如下:
scripts/app/proxy/validation.js
(function() {
var log = pure.log("proxy.validation");
proxy.validation = { priority: 60 };
proxy.validation.saveUser = {
priority: 100,
expr: /^dbo.users.save$/,
func: function(name, method, args) {
// 获取验证结果
var validated = validator.validateUser(args[0]);
// 验证失败,抛出异常
if (!validated.success) {
log.info(validated.error);
throw validated.error;
}
var data = validated.data;
// 检查用户是否已经存在
// 注意,这里的 this 表示 dbo 对象
if (this.exists(data.name)) {
var msg = "Save User Faild: User already exists.";
log.info(msg);
throw msg;
}
// 通过验证,返回所需的结果
args[0] = data;
return this[method].apply(this, args);
}
}
}());
webapp/js/index.js
$(function(){
// 其他代码,略
function save(user, callback) {
// 获取验证结果
var validated = validator.validateUser(user);
// 验证失败,显示异常
if (!validated.success) {
$("#error").html(validated.error);
return;
}
var data = validated.data;
// 检查用户是否已经存在
for (var i = 0, l = users.length; i < l; ++i) {
if (users[i].name === data.name) {
$("#error").html("User already exists.");
return;
}
}
callback(data);
show();
pure.post({ action: "users.save", params: data });
}
});
可以看到,检查输入是否为空和检查输入参数长度的部分是共用的,但检查用户是否存在的逻辑在客户端和服务器端略有不同。
另外,proxy 对象的 func 中 的 this 表示的是被截获的对象,因此我们可以在 proxy.validation.saveUser 中调用 dbo.exists(name) 来检查用户是否已经存在。
小结
1. 我们可以利用 proxy 对象拦截方法的调用,进行权限和数据的检查
2. 我们可以将服务器和浏览器端共用的代码放在 both 目录下
3. proxy 对象的 func 中 的 this 表示的是被截获的对象
分享到:
相关推荐
NULL 博文链接:https://xxing22657-yahoo-com-cn.iteye.com/blog/1136195
Js中Proxy对象 Proxy对象用于定义基本操作的自定义行为,例如属性查找、赋值、枚举、函数调用等。 语法 const proxy = new Proxy(target, handler); target: 要使用Proxy包装的目标对象,可以是任何类型的对象,...
Js中Proxy对象 Proxy对象用于定义基本操作的自定义行为,例如属性查找、赋值、枚举、函数调用等。 语法 const proxy = new Proxy(target, handler); target: 要使用Proxy包装的目标对象,可以是任何类型的...
实现mysql读写分离。 forking socket模型。
js代码-利用 Proxy 包裹对象
详细介绍ArcGIS JS API跨域配置 介绍Proxy 代理不同web服务器环境部署和调用
HPMIPv6:Hierarchical Proxy MIPv6,胡为松,谢东亮,基于网络的移动性管理协议PMIPv6不需要节点参与移动性相关信令交互,有效的降低了移动节点上的能量消耗,非常适合6LoWPAN网络低功耗��
A js proxy online or js packer offline.See help.html for more information.
MySQL Proxy 实现负载均衡测试 MySQL Proxy 实现负载均衡测试
NULL 博文链接:https://xxing22657-yahoo-com-cn.iteye.com/blog/1159366
这是ES6 Proxy的polyfill,支持IE6 + ,Node.js等。 到目前为止,它比GoogleChrome的支持更多功能。 polyfill仅支持有限数量的代理“陷阱”: 得到 放 申请 构造 还支持Proxy.revocable方法,但仅适用于对上述...
解决代理转发post请求失败
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)
安装curl https://raw.githubusercontent.com/EtherDream/jsproxy/0.1.0/i.sh | bash自动安装目前只支持Linux x64,并且需要root权限安装过程中80扩展能被外网访问(申请HTTPS证书)无法满足上述条件,或想了解安装...
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)
JavaScript 的深度代理 这是proxy-deep包的开发存储库,可在。 要安装软件包,只需发出: npm i proxy-deep 要么 yarn add proxy-deep 文档。 执照 这个存储库中的所有代码都是 MIT 许可的。
proxy代理程序实例和讲解 网络编程详细代码实现和讲解
使用mysql5.7+sharding-proxy实现分表,策略为每半年时间分一次表