如何确保休眠版本号在 javascript 客户端中保持不变?
How to ensure that the hibernate version number stays immutable in a javascript client?
我有一个带 Java 和 Hibernate 的 Rest 后端,我使用 属性 版本的乐观锁定。
对于并发控制,此版本 属性 必须发送到客户端,然后使用 post 请求再次发送到服务器。
但是,在 javascript 客户端中,我无法控制此 属性 的完整性,例如:
- 客户端 "A" 请求资源 1。
- 客户端 "B" 请求相同的资源。
- 服务器用资源 1 版本 1 响应两个客户端(在它们各自的响应中)
- 客户端"A"修改资源并post保存修改。
- 服务器处理 post 请求,Hibernate 检查版本号。 1 = 1 所以资源被修改。
- 客户端B玩javascript修改版本属性为2,发起post请求。
服务器处理post请求,现在2=2,所以资源被修改,客户端A所做的修改丢失。
记住这是一个 Rest 后端,因此我无法在服务器中保存交付给每个用户的对象的版本号,o 类似的东西。
那么,如果这是一个像我认为的那样有效的问题,我如何确保版本在客户端中保持不变?
使用将数字隐藏在只读后面的构造函数 getter:
var MyObject = function(version) {
var _version = version;
this.getVersion = function() { return _version; }
}
或者,使用 getter 和 setter 对,只允许设置一次变量:
var MyObject = function() {
var self = this;
var _tripwire = false;
var _value = null;
self.setValue = function(val) {
if (_tripwire==false)
_tripwire = true;
else
throw "Value is read-only";
_value = val;
};
self.getValue = function() {
return val;
}
};
根据您希望它失败的方式,您可以将 throw 语句替换为 return 静默吃掉 属性 集,但对于 API 代码,当调用者做一些非常不安全的事情,还不如大声而自豪地死去。
请注意,如果您更喜欢 属性 风格的访问方法,您也可以使用 属性 访问器完成相同的设计模式:
function setOnceProp(o, name) {
var _value = null;
var _tripwire = false;
Object.defineProperty(o, name, {
get: function() {
return _value;
},
set: function(newValue) {
if (_tripwire==false)
_tripwire = true;
else
throw "Value is read-only";
_value = newValue;
},
enumerable: true
});
}
var MyObject = function() {
var self = this;
setOnceProp(self, 'value');
};
这确实需要您的客户使用相对较新的浏览器。
就我个人而言,我会重新考虑这样做,因为我认为客户几乎没有这样做的动机,而且根据定义,您无法控制客户向您的 REST 服务发送的内容。
但是,如果您确实有业务案例,那么一个半解决方案是使版本 属性 成为 GUID。这样,您只有在拥有最新的 GUID 时才能提交,而客户端 B 没有,这会使版本控制情况更加复杂,因为在请求成功之前您不能只递增 1。
但是,即使在那里您也不是完全安全的,因为客户端 B 理论上可以执行单独的请求以从资源中获取更新的 GUID,然后使用更新的 GUID 重新提交失败的请求。
但是由于客户 B 可以对更新版本进行编辑以恢复客户 A 所做的并添加他们自己的,这与这样做本质上是一样的,并且由于他们有权这样做,我们回来了问问自己为什么我们首先再次担心那个案子。
我有一个带 Java 和 Hibernate 的 Rest 后端,我使用 属性 版本的乐观锁定。 对于并发控制,此版本 属性 必须发送到客户端,然后使用 post 请求再次发送到服务器。 但是,在 javascript 客户端中,我无法控制此 属性 的完整性,例如:
- 客户端 "A" 请求资源 1。
- 客户端 "B" 请求相同的资源。
- 服务器用资源 1 版本 1 响应两个客户端(在它们各自的响应中)
- 客户端"A"修改资源并post保存修改。
- 服务器处理 post 请求,Hibernate 检查版本号。 1 = 1 所以资源被修改。
- 客户端B玩javascript修改版本属性为2,发起post请求。 服务器处理post请求,现在2=2,所以资源被修改,客户端A所做的修改丢失。
记住这是一个 Rest 后端,因此我无法在服务器中保存交付给每个用户的对象的版本号,o 类似的东西。
那么,如果这是一个像我认为的那样有效的问题,我如何确保版本在客户端中保持不变?
使用将数字隐藏在只读后面的构造函数 getter:
var MyObject = function(version) {
var _version = version;
this.getVersion = function() { return _version; }
}
或者,使用 getter 和 setter 对,只允许设置一次变量:
var MyObject = function() {
var self = this;
var _tripwire = false;
var _value = null;
self.setValue = function(val) {
if (_tripwire==false)
_tripwire = true;
else
throw "Value is read-only";
_value = val;
};
self.getValue = function() {
return val;
}
};
根据您希望它失败的方式,您可以将 throw 语句替换为 return 静默吃掉 属性 集,但对于 API 代码,当调用者做一些非常不安全的事情,还不如大声而自豪地死去。
请注意,如果您更喜欢 属性 风格的访问方法,您也可以使用 属性 访问器完成相同的设计模式:
function setOnceProp(o, name) {
var _value = null;
var _tripwire = false;
Object.defineProperty(o, name, {
get: function() {
return _value;
},
set: function(newValue) {
if (_tripwire==false)
_tripwire = true;
else
throw "Value is read-only";
_value = newValue;
},
enumerable: true
});
}
var MyObject = function() {
var self = this;
setOnceProp(self, 'value');
};
这确实需要您的客户使用相对较新的浏览器。
就我个人而言,我会重新考虑这样做,因为我认为客户几乎没有这样做的动机,而且根据定义,您无法控制客户向您的 REST 服务发送的内容。
但是,如果您确实有业务案例,那么一个半解决方案是使版本 属性 成为 GUID。这样,您只有在拥有最新的 GUID 时才能提交,而客户端 B 没有,这会使版本控制情况更加复杂,因为在请求成功之前您不能只递增 1。
但是,即使在那里您也不是完全安全的,因为客户端 B 理论上可以执行单独的请求以从资源中获取更新的 GUID,然后使用更新的 GUID 重新提交失败的请求。
但是由于客户 B 可以对更新版本进行编辑以恢复客户 A 所做的并添加他们自己的,这与这样做本质上是一样的,并且由于他们有权这样做,我们回来了问问自己为什么我们首先再次担心那个案子。