用户脚本中@include和@match有什么区别?

WBT*_*WBT 30 javascript greasemonkey userscripts tampermonkey

元数据块上GreaseSpot页面说两者非常相似,但@match"对*字符的含义设置了更严格的规则".然后GreaseSpot继续教授使用@include,但像这样的 Chrome示例通常似乎使用@match并表明@include仅支持兼容性目的; @match是优选的.

显然,@include google.*可以在google.evil.com上运行而@match google.*不能.
这个例子不足以真正看出通配符在这两者之间的表现如何不同,并且在这里的答案中寻求更好的解释.

@include默认情况下使用新的GreaseMonkey脚本(Firefox),而默认使用新的TamperMonkey脚本(例如Chrome)@match.

这两者之间到底有什么区别?

例如,每个人如何处理通配符?
跨浏览器兼容性有差异吗?
有人选择使用一个而不是另一个的原因是什么?

WBT*_*WBT 21

您不能将正则表达式与@match一起使用,而可以使用@include.

但是,@ include会为您的用户提供有关应用于所有网站的脚本的更可靠的安全警告.

即使@include表达式允许您对脚本应用的站点进行更严格的限制(例如,使用正则表达式片段"[0-9] +"指定URL的一部分,或使用"^ https? ://"只为这两个方案应用于脚本,而不是在@match中用于每个案例的更通用的非正则表达式运算符*,这会导致脚本更广泛地应用).

  • 在[Tampermonkey论坛](https://forum.tampermonkey.net/viewtopic.php?t=466)中可以找到`@ match`通配符比`@include`通配符更安全的示例:`@include http*: //*.biniok.net`允许http://evil.de#biniok.net,`@match http*://*.biniok.net`不允许. (4认同)
  • @dkasak `@include http*://*.biniok.net` 被解释为 globs。要解释为正则表达式,它应该是`@include /http*://*.biniok.net/`。此外,`@include /http*://*.biniok.net/` 与 http://evil.de/#biniok.net 不匹配;它匹配类似`htt:/1biniok2net` 或`httppppp://////xbiniokynet` (2认同)

zco*_*p98 20

TL;DR:刚性

最重要的区别是 比@match更严格的结构和限制@include,这使其成为更“普遍”安全(也是首选)的变体。@match由于这种刚性,整体使用起来可能会稍微复杂一些,但@include可能会向最终用户产生更可怕的警告,因为它更容易误用。

两者的实际用法可能有很大差异;下面是每种用途的完整细分。


@include(和@exclude

@include可能是大多数人更熟悉的指令(以及它的对立孪生指令 ,@exclude它具有完全相同的语法特征)。与 相比,这是更强大、更灵活的指令@match,主要是因为它可以处理 RegEx 模式。它的用法也是最直接的。

模式

您可以@include通过两种方式指定模式/“模式”:

全局模式

在“glob 模式”中,星号*可用作通配符 glob,表示模式中的给定位置允许使用任意数量的字符(包括零)。通过GreaseMonkey 文档

例如:http://www.example.com/foo/*将匹配:

  • http://www.example.com/foo/bar和,
  • http://www.example.com/foo/

但不是:

  • http://www.example.com/baz/

还有一种特殊模式可用于@include匹配任何顶级域后缀:.tld. 类似的模式@include https://www.example.tld/*会将给定域与任何有效的公共 TLD 后缀(例如.com.org或 )相匹配.co.uk

正则表达式模式

@include以正斜杠开头的指令/将被解释为正则表达式,并提供所有标准 JavaScript RegEx 功能:

// ==UserScript==
// @include     /^https?://www\.example\.com/.*$/
// @include     /^http://www\.example\.(?:org|net)//
// ==/UserScript==
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  • 由于 JavaScript 的 RegEx 解释,/不需要在表达式内转义正斜杠。
  • 其他特殊字符仍然需要转义。
  • @include模式始终被视为不区分大小写
  • 不以 EOL 标记结尾的表达式$ 将隐式允许匹配上的尾随字符
    • 即表达式被视为以 结尾.*
    • @include /^https?://www\.google\.com/search/ 匹配https://www.google.com/search?q=stackoverflow.

警告

请记住, 的强大且广泛的性质@include意味着浏览器无法像@match. 这意味着@include在某些情况下,使用的脚本可能会向用户触发听起来很严重的警告。

最常被提及的使用危险之一@include是无意(或有意恶意)的 URL 匹配;@include当模式的作用域没有被正确确定或理解时,或者当坏人制作一个 URL 来专门触发不打算运行的脚本时,就会发生这种情况。

由于非 RegEx 通配符可以匹配 URL 中任何位置的任何字符,因此看似简单的模式可能会出现意外的匹配。例如,人们可能期望*://example.net/*只匹配属于该example.net域的 URL,但它也会匹配https://evil.com/?http://example.net/!

一些用户脚本管理器具有内置的保护措施来帮助减轻此类攻击向量,但这种可能性仍然存在,这使得@include潜在的危险性比 更危险@match,后者的设计目的是在很大程度上免受这种类型的攻击。


@match

@match指令是 Google 为 Chrome 创建的,旨在成为该@include指令的更安全、沙盒化版本,内置了更多的刚性。

不支持 glob 或 RegEx,而是@match将模式解释为 3 部分:方案主机路径谷歌的文档是这样描述基本语法的:

<url-pattern> := <scheme>://<host><path>
<scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'urn'
<host> := '*' | '*.' <any char except '/' and '*'>+
<path> := '/' <any chars>
Run Code Online (Sandbox Code Playgroud)

该模式的每个部分都有其自己的注意事项,并且对通配符的解释也*不同

方案

URL 模式的方案部分必须与浏览器支持的方案完全匹配或者是通配符*。但请注意,通配符不允许所有方案,而是仅匹配httphttps

浏览器 匹配模式支持的方案
铬合金 httphttpsfileftp, 或者urn
火狐浏览器 httphttpsfileftpwswssdata, 或者 (chrome-extension
苹果浏览器 至少1 httphttps
  1. 我找不到关于 Safari 在清单中支持哪些方案的全面参考。Mozilla 将其跟踪为缺少除http和之外的所有内容https,但他们缺少其他浏览器的完整列表(例如urn缺少,Chrome 支持),因此 Safari 可能仍支持其他方案。

这里对通配符的一个警告是,特别是在 Firefox 中(也可能是其他浏览器,但尤其不是Chrome 或 Safari),通配符还将匹配 WebSocket 方案wswss.

主持人

URL 模式的主机部分可以采用三种样式:

  • 完全明确:www.stackoverflow.com
  • 子域通配符:*.stackoverflow.com
  • 完全通配符:*

顶级域名后缀不能是通配符(例如www.stackoverflow.*);出于安全原因,这是不允许的。为了匹配多个 TLD 后缀,脚本需要@match为每个后缀包含一个特定指令。

小路

URL 模式的路径部分是最宽松的,因为唯一的规则是它必须以正斜杠开头/。其余的可以是字符和通配符的任意组合。

在本节中,通配符*充当标准的全局运算符,仅匹配 0 个或多个字符。

与模式的路径部分匹配的值正式为URL 路径加上URL 查询字符串(例如,在 中google.com/search?q=test,查询字符串为q=test),包括?其间。对于旨在匹配给定域末尾的模式来说,这是一个潜在的陷阱,因为它们可能会被添加的查询字符串所挫败。

另请注意,该路径不包含URL 片段(URL 末尾跟随 hash 的部分#,例如www.example.com#main);@match指令在设计上会忽略 URL 片段,以防止滥用无意的匹配。


警告

这是相当明显的,但值得重复的是,脚本应该注意@include 准确排他地运行脚本的 URL。失控脚本的范围可以从小烦恼到大问题;始终仔细检查脚本是否仅在应有的位置运行,并@exclude在必要或方便时添加护栏。