【问题标题】:What is the difference between @include and @match in userscripts?用户脚本中的@include 和@match 有什么区别?
【发布时间】:2015-10-27 08:36:14
【问题描述】:

GreaseSpot page on metadata blocks 表示两者非常相似,但@match“对* 字符的含义设置了更严格的规则。” GreaseSpot 然后使用@include 继续到teach,但像this 这样的Chrome 示例通常似乎使用@match 并表明@include 仅出于兼容性目的而支持;首选@match

Apparently@include google.* 可以在 google.evil.com 上运行,而 @match google.* 不能。
仅此一个示例不足以真正了解通配符在这两者之间的行为有何不同,此处的答案中寻求更好的解释。

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

这两者到底有什么区别?

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

【问题讨论】:

  • 像其他人一样使用include。我已经这样做了多年,没有任何问题。
  • @MortenMoulder 那是……呃……????不一定是好事。该问题明确给出了一个可能由此产生的问题的示例。仅仅因为您的用户都没有从中获得 pwned(或者,至少没有这样的人制造新闻)并不意味着它是安全的,尤其是当“仅使用包含”没有提及时使用它时必须采取的必要预防措施,这个非常好的问题的很好的答案解释了这一点。

标签: javascript greasemonkey userscripts tampermonkey


【解决方案1】:

TL;DR:刚性

最重要的区别是@match@include 更加严格和限制性更强,旨在成为更安全的替代方案。出于这个原因,@include 也可能对最终用户产生更可怕的警告;它的整体使用也有点复杂,具体取决于您如何看待它。

这两者的实际用法实际上可以有很大的不同;以下是每种用法的完整细分。


@include(和@exclude

@include 可能是大多数人更熟悉的指令(以及它的对立双胞胎@exclude,它具有完全相同的语法特征)。这是两者中更强大的指令,主要是因为它可以处理 RegEx 模式(这也意味着它会产生更可怕的警告)。它的用法也是两者中最直接的。

模式

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

全局模式

星号* 可用作wildcard glob,即表示任何个字符,包括零。

For example:

  • @include http://www.example.com/foo/*:
    • 匹配 http://www.example.com/foo/http://www.example.com/foo/bar
    • 匹配http://www.example.com/baz

还有一种特殊模式可用于专门匹配任何顶级域后缀:.tld

@include https://www.example.tld/* 之类的模式将与给定域匹配任何顶级域 后缀,例如.com.org.co.uk

正则表达式模式

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

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

一些注意事项:

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

警告

请记住,@include 的强大特性意味着浏览器不能像使用 @match 的脚本那样保证给定脚本的目标;这意味着使用@include 的脚本可能会为用户触发更可怕和更严重的警告。

不使用 @include 的一个常见原因涉及 URL 片段(在哈希 # 字符之后的 URL 部分),以及恶意行为者如何滥用它们在不受欢迎的页面上执行脚本(例如 @ 987654362@ 可以匹配 www.evil.com#www.example.com/),因为 @match 在设计上会忽略片段。

虽然这种攻击在理论上仍然是可能的,但值得牢记的是,一些用户脚本管理器(包括 Tampermonkey)故意完全忽略片段以进行匹配,即使在 @include 指令中也是如此。


@match

@match 指令是 Google for Chrome 的创建,旨在作为 @include 指令的更安全、更沙盒化的版本,内置更多更加严格。

@match 不允许使用 glob 或 RegEx,而是将模式解释为 3 个部分:schemehostpath . Google's documentation 这样描述基本语法:

<url-pattern> := <scheme>://<host><path>
<scheme> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'urn'
<host> := '*' | '*.' <any char except '/' and '*'>+
<path> := '/' <any chars>

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

方案

URL 模式的方案部分必须与支持的方案之一(这似乎取决于浏览器)或通配符 * 完全匹配。

  • 在 Chrome 中,即:httphttpsfileftpurn
  • In Firefox,这似乎是 httphttpsfileftpwswssdata 或 (chrome-)extension

在这部分模式中,通配符*完全匹配httphttpsMDN mentions,它也可能匹配WebSocket方案wswss在某些情况下浏览器)。

主机

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

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

顶级域后缀不能是通配符(例如www.stackoverflow.*); this is disallowed for security reasons。为了匹配多个 TLD 后缀,脚本需要为每个后缀包含一个特定的 @match 指令。

路径

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

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

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

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


注意事项

这是相当明显的,但需要重复的是,脚本应该小心@include完全完全脚本打算在其上运行的 URL。失控脚本的范围可以从无法检测到的轻微烦恼到重大问题;始终仔细检查脚本是否仅在它们应该在的地方运行,并在必要或方便时使用@exclude 添加护栏。

【讨论】:

    【解决方案2】:

    您不能将正则表达式与@match 一起使用,而can@include 一起使用。

    但是,@include 会针对适用于所有网站的脚本向您的用户发出更可怕的安全警告。

    即使@include 表达式允许您对脚本适用的站点更严格(例如,使用正则表达式片段 [0-9]+ 指定 URL 的部分是数字,或使用^https?:// 将这两种方案应用于脚本,而不是@match 中用于每种情况的更通用的非正则表达式通配符*,这会导致脚本应用更广泛)。

    【讨论】:

    • @match 通配符比@include 通配符更安全的示例可以在Tampermonkey forum 中找到:@include http*://*.biniok.net 允许evil.de#biniok.net@match http*://*.biniok.net 不允许。
    • @dkasak @include http*://*.biniok.net 被解释为 glob。要解释为正则表达式,它应该是@include /http*://*.biniok.net/。另外,@include /http*://*.biniok.net/ 不匹配 evil.de/#biniok.net ;它匹配 htt:/1biniok2nethttppppp://////xbiniokynet
    猜你喜欢
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2023-03-26
    • 2010-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多