- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
HTTP / WebDav规范是否允许此客户端-服务器对话框?
客户端:我想将数据放入/user1/foo.mkv中,该哈希值是:HASH
服务器:好的,PUT成功,您不需要发送数据,因为我已经知道带有此哈希和的数据。
注意:此PUT是初始上传。这不是更新。
如果可能的话,可以实现一种更快的文件同步方式。
用例:WebDAV服务器为每个用户托管一个目录。最喜欢的视频foo.mkv被多个用户上传。在此示例中,喜爱的视频已经存储在以下位置:/user2/myfoo.mkv。由于服务器已经知道内容,因此第二次及之后的上载不需要发送任何数据。这将减少很多网络负载。
前提条件:
客户端和服务器需要事先就哈希算法达成共识。
服务器需要存储已知文件的哈希值。
在自定义客户端和服务器中实施此操作非常容易。但这不是我想要的。
我的问题:是否存在允许此类对话的RFC或其他标准?
如果还没有标准,那么如何实现这个梦想呢?
安全考虑
通过上面的对话框,将能够访问已知哈希的内容。例如,一个邪恶的客户知道存在一个哈希值为1234567...
的文件。他可以执行上述两个步骤,然后客户端可以使用GET下载数据。
扩展对话框的一种方法:
客户端:我想输入具有该哈希值的数据:哈希
服务器:好的,PUT将成功,但是要确保您具有数据,请向我发送字节N到M。我需要这样做,以确保您具有哈希和和数据。
客户端:数据的第N个字节(最多M个)为abcde...
服务器:好的,您的字节匹配我的。我信任你。上传成功,您无需再发送数据。
如何做到这一点?
由于似乎还没有规范,因此问题的这一部分仍然存在:
如何实现这个梦想?
最佳答案
根据您的描述,似乎应该使用ETag。
它是专门设计用于将标签(通常是MD5哈希,但可以是任何东西)与资源的内容(和/或位置)相关联,以便您以后可以知道资源是否已更改。
EUT支持PUT请求,并且commonly used具有optimistic concurrency control的If-Match
标头。
但是,您的用例略有不同,因为您尝试阻止对内容相同的资源进行PUT,而If-Match
标头用于仅允许对内容相同的资源进行PUT。
在您的情况下,可以改用If-None-Match
标头:
“ If-None-Match:*”的含义是该方法不得为
如果原始服务器(或
缓存,可能使用Vary机制,请参阅第14.44节),
如果该表示不存在,则应该执行。这个
该功能旨在防止PUT之间的竞争
操作。
WebDAV also supports Etags尽管其用法可能取决于实现:
请注意,在PUT响应中ETag的含义不清楚
在本文档或RFC 2616中定义(即ETag是否
表示该资源的八位字节等于八位字节的主体
PUT请求,或者服务器是否可以进行较小的更改
在存储时文档的格式或内容中)。这是一
HTTP问题,而不仅仅是WebDAV问题。
如果您要实现自己的客户,我将执行以下操作:
客户端向资源发送HEAD请求,检查ETag
如果客户端发现它匹配已经存在的内容,请不要发送其他任何内容
如果不匹配,则发送带有If-None-Matches
标头的PUT请求
更新
从更新的问题来看,现在似乎很清楚,当收到PUT请求时,您想要在接受请求之前检查服务器上的所有资源是否缺少相同的内容。这还意味着还要检查与指定为PUT请求的目的地的位置不同的资源。
AFAIK,目前没有专门处理这种情况的规范。但是,ETag机制(和HTTP协议)被设计为通用且足够灵活以处理许多情况,这就是其中一种。
当然,这仅意味着您无法利用标准的HTTP服务器逻辑-您需要自定义客户端和服务器端的代码。
假设条件
在进行可能的实现之前,需要进行一些假设。
如前所述,您需要同时控制服务器和客户端
需要同意一种基于内容生成ETag的算法。可以是MD5,SHA1,SHA2-256,SHA3,它们的组合的串联等等。我仅将算法输出作为ETag提及,但是如何实现取决于您自己。
可能的实施
如果简单的情况对您不起作用,则将这些命令从最简单到逐渐增加的复杂程度排序。
可能的实施方式1
假定您的服务器实现允许您读取请求标头并在接收到整个请求之前进行响应。
客户端计算要上传的文件/资源的ETag。
客户端使用包含ETag的标头If-None-Match
向服务器发送PUT请求(位置无关紧要),然后继续正常发送正文。
服务器检查以查看是否已经存在带有ETag的资源。
服务器:
如果ETag已经存在,请立即返回412响应代码。 (可选)终止连接以阻止客户端继续发送资源(注意:尽管没有明确禁止,但HTTP规范不建议这样做。请参阅下面的注释1)。是的,浪费了一点带宽,但是您不必等待整个请求完成。
如果ETag不存在,请等待请求正常完成。
客户:
如果收到412响应,请对其进行解释,以使资源已经存在并且需要中止请求-停止发送数据。
可能的实施方式2
这稍微复杂一点,但是更好地遵循了HTTP规范。另外,如果在接收到整个请求之前您的服务器体系结构doesn't allow you to read the headers,则此MIGHT可以工作。
客户端计算要上传的文件/资源的ETag。
客户端使用包含ETag的标头If-None-Match
和Expect: 100-continue
标头向服务器发送PUT请求(位置无关紧要)。此时尚未发送请求正文。
服务器检查以查看是否已经存在带有ETag的资源。
服务器:
如果ETag已经存在,则返回412 response。
如果ETag不存在,请发送100 response并等待请求正常完成。
客户:
如果收到412响应,请对其进行解释,以使资源已经存在,因此请求中止。
如果收到100响应,请继续正常发送正文
可能的实施方式3
此实现可能需要最多的工作,但应与所有主要的库/体系结构广泛兼容。但是,另一个客户端在两个请求之间上传具有相同内容的文件的风险很小。
客户端计算要上传的文件/资源的ETag。
客户端将HEAD请求(无正文)发送到/check-etag/<etag>
处的服务器,其中<etag>
是ETag。这将检查服务器上是否已经存在ETag。/check-etag/*
处的服务器代码检查是否存在带有该ETag的资源。
服务器:
如果ETag已经存在,则返回200响应。
如果ETag不存在,请发送404响应。
客户:
如果收到200响应,请对其进行解释,以使资源已经存在并且不继续进行PUT请求。
如果收到404响应,请向目标目的地发送正常的PUT请求。
注意事项
尽管具体实现取决于您,但是需要考虑以下几点:
添加或更新资源时,应将ETag和位置存储在数据库中以便快速检索。每当资源上载时,服务器为每个单个资源重新计算哈希值都是不必要的低效率。 ETag和位置字段上还应该有一个索引,以便快速检索。
如果两个客户端同时上传具有相同ETag的资源,则您可能希望在第一个客户端完成后立即中止第二个客户端。
对ETag使用散列意味着存在冲突的可能性(其中两个资源将具有相同的散列),尽管在实践中,如果使用良好的散列,则可能性极小。注意,已知MD5对故意collision attacks较弱。如果您偏执狂,可以将多个散列连接起来,使碰撞的机率小得多。
关于您的“安全考虑”,我仍然看不到知道哈希如何导致资源检索。服务器只会并且应该仅告诉您是否存在特定的ETag。如果不泄露位置,客户端将无法检索文件。即使客户端知道位置,服务器也应该实施其他安全控制,例如身份验证和授权来限制访问。仅将资源位置用作限制访问的方法只是出于安全考虑(尤其是因为您提到的那样,路径似乎遵循用户名的模式)。
笔记
RFC 2616指示不应这样做:
如果原始服务器收到不包含Expect的请求
期望值为“ 100-continue”的请求标头字段
包括一个请求主体,服务器以最终状态响应
从传输读取整个请求正文之前的代码
连接,则服务器不应关闭传输连接
直到读取了整个请求,或者直到客户端关闭
连接。否则,客户端可能无法可靠地收到
响应消息。
另外,请勿在没有发送任何状态代码的情况下关闭服务器端的连接,因为客户端很可能会重试该请求:
如果HTTP / 1.1客户端发送包含请求正文的请求,
但其中不包含带有
预期为“ 100-继续”,并且客户不是直接
连接到HTTP / 1.1原始服务器,并且如果客户端看到
在从服务器接收任何状态之前,连接已关闭,
客户应该重试该请求。
关于hash - HTTP规范:不进行数据传输的PUT,因为服务器知道数据的哈希值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32794863/
我正在尝试使用 Rust 的 std::hash 函数: use std::hash::{hash, Hash, SipHasher}; #[test] fn hash_test() { pr
我有以下内容 friends = [{ name: "Jack", attr1:"def", attr2:"def" }, { name: "Jill", attr1:"def", attr2:"de
我有以下数组: names = [ {"Adriana"=>{:gender=>"female", :nationality=>"danish"}}, {"Adriane"=>{:gender=>"f
我有一个哈希的 Perl 哈希......大约 11 或 12 个元素深。请原谅我没有重复下面的结构! 一些级别有固定的标签,例如'NAMES' , 'AGES'或类似的,因此访问这些级别很好,因为我
我试图派生一个描述结构化值的Graphviz文件。这是出于诊断目的,因此我希望我的图形尽可能接近地反射(reflect)内存中的实际结构。我正在使用下面的方法将值映射到Graphviz顶点,以便当一个
我正在尝试获取在 xlm 中传递的事件日志条目,将它们转换为散列,然后存储到数据库中。 我目前正在使用 XmlSimple gem 将 xml 输入转换为散列。 测试样本输入: require 'xm
对于 Ruby 中的 Hash,reject! 和 reject 与 delete_if 有何不同?谁能用简单的代码片段解释它们之间的区别? 最佳答案 由于其他答案指的是 Array#delete_i
我正在尝试处理我使用 Data::Dumper 输出的 perl 数据结构 $VAR1 = 'GAHD'; $VAR2 = [ { 'COUNTRY' => 'US',
无法使用来自辅助进程的现有 rte Hash: h = rte_hash_find_existing("some_hash"); if (h) { // this will w
我有一个散列的散列,其中第一个键是一个字符串,第二个键是一个整数。我试图在散列的散列中获得最低的第二个键。这是我的哈希。 %HoH = ( flintstones => { 8
如何从一系列数组中生成哈希中的哈希?我需要从这里开始: my @data = /one two three/; my $value = 13: 为此: $hoh = { 'one' => { 'two
我有这个配置文件 dbUser=customer dbPass=passwrd dbSid=customer.shadow passwdFile=/production/etc-user tmpUse
我想实现一种thing,可以唯一标识,除此之外,它不包含其他字段。它有点像 ruby 中的 BasicObject 或 java 中的 Object。 我添加了一个 PartialEq 特征。 s
我正在尝试使用以下键存储二维哈希: 维度 1 = 数字但不连续 维度 2 = 字符串(如 :id 和 :value) 当元素未初始化时会出现问题。 memory = Hash.new(Hash.new
我目前正在学习 Michael Hartl 的 Ruby on Rails 教程 不理解在 section 4.4.1 中找到的此语句的含义: Hashes, in contrast, are dif
我很乐意通过更短的表达式访问多维哈希数组的任何元素 h = {a: {b: 'c'}} # default way p h[:a][:b] # => "c" # a nicer way p h[:a,
我想在编写 flutter channel beta 后运行 flutter web 它回复:Can't load kernel binary:Invalid SDK hash,你知道如何解决这个问题
我最近正在研究 Amazon 提供的新 NoSQL 服务,更具体地说是 DynamoDB。 亚马逊说你应该避免使用不均匀分布的键作为主键,即主键应该越独特越好。我可以认为这是最好的情况下每个项目都有唯
我的游戏中有很多哈希值,例如 HMSET('hash1', 'level', 25, 'connected', 2) HMSET('hash2', 'level', 50, 'connected',
我必须翻译这句话:'Susspected overpass-the-hash attack (Kerberos)' 我发现了这篇关于立交桥哈希的文章:https://blog.stealthbits.
我是一名优秀的程序员,十分优秀!