有没有办法在新的 Google 站点上允许来自 Cloudflare 的脚本?
Is there a way to allow scripts from Cloudflare on new Google sites?
我使用新的 Google 网站(不是经典网站)创建了一个网站,通过 Cloudflare 设置了网站代理,并启用了 Email Address Obfuscation 功能在 Cloudflare 中。然后我添加了一个执行简单操作的按钮 mailto:info@example.com
和 运行 到一个问题中:当我单击该按钮时,我被带到 Cloudflare“电子邮件保护”页面,并显示消息“您无法访问此电子邮件地址 example.com".
这是出于一个简单的原因 - 我的浏览器(任何现代浏览器都会出现这种情况)不会从 Cloudflare 加载 email-decode.min.js
脚本。反过来,这是由于 Google Sites 使用 CSP >= v2 并且 CSP 指令的配置方式不允许从 Cloudflare 加载脚本。
根据 Cloudflare 文档,为了使用 Scrape Shield you need to update CSP headers 如下:
script-src 'self' 'unsafe-inline'
这是新的 Google Sites CSP header 的样子:
base-uri 'self';
object-src 'none';
report-uri /_/view/cspreport;
script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval';
worker-src 'self';
frame-ancestors https://google-admin.corp.google.com/
* nonce-<base64-value>
随每个请求更新。
加载包含电子邮件的页面时,我在浏览器控制台中看到以下错误:
Refused to load the script 'https://example.com/cdn-cgi/scripts/6d6ddgh8/cloudflare-static/email-decode.min.js' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
我不确定原因,但由于以下两个原因之一,脚本无法加载:
- 源
'self'
没有为 script-src
指令设置(我不认为是这种情况)。
- 源
'unsafe-inline'
被忽略,因为存在加密随机数。
无论如何都行不通。我看到两个解决方案,但我不知道如何实现它们:
- 对于第一个原因(尽管我不认为是这种情况),如果 Google 将源代码
'self'
添加到 script-src
指令中,或者如果我有能力定制这个 header 我会自己做。
- 对于第二个原因,如果 Cloudflare 在请求站点时读取 Google 服务器 returns 的
'nonce-<base64-value>'
并将其添加到其脚本中,则可以解决此问题。
如果有人能分享这个问题的解决方案,将不胜感激。
所以我发现原因是 script-src
指令中缺少 'self'
源。
我找到了一个允许在请求/响应中替换 header 的工作人员 forum thread that suggests using Cloudflare Workers to change the required data in a request / response on the fly. I also found a ready-made example code。
受到这个想法的启发,鉴于 Cloudflare 每天免费提供 100,000 个请求,我编写并部署了一个更改服务器响应 header 的工作代码,实际上,它更新了 script-src
指令在 content-security-policy
header 中,用变量 sources
.
中指定的源对其进行补充
我的问题已解决,现在正在加载 Cloudflare 脚本并且按钮可以使用。
* 我不保证代码质量,但它确实有效。代码可以变得更加通用,但我没有时间。
这是我的工人代码:
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
const sources = ["'self'"]
/**
* The function to update a CSP directive with new sources.
* @param {string} directive CSP directive.
* @param {string[]} sources Sources to add to the directive.
* @return {string} Updated CSP directive.
*/
function updateDirective(directive, sources) {
for (let i = 0; i < sources.length; i++) {
if (!directive.toLowerCase().includes(sources[i])) {
directive = directive.concat(" ", sources[i])
}
}
return directive
}
/**
* The function to update the Content-Security-Policy header.
* @param {string} header The Content-Security-Policy header.
* @param {string} directive The Content-Security-Policy directive whose sources need to be updated.
* @param {string} sources Sources to add to the directive.
* @return {string} Updated Content-Security-Policy header.
*/
function updateHeader(header, directive, sources) {
let sourceHeader = header.split(';')
let updatedHeader = []
for (let i = 0; i < sourceHeader.length; i++) {
if (sourceHeader[i].includes(directive)) {
updatedHeader.push(updateDirective(sourceHeader[i], sources))
} else {
updatedHeader.push(sourceHeader[i])
}
}
return updatedHeader.join(";")
}
async function handleRequest(request) {
let response = await fetch(request)
response = new Response(response.body, response)
response.headers.set('content-security-policy',
updateHeader(response.headers.get('content-security-policy'), "script-src", sources))
return response
}
我使用新的 Google 网站(不是经典网站)创建了一个网站,通过 Cloudflare 设置了网站代理,并启用了 Email Address Obfuscation 功能在 Cloudflare 中。然后我添加了一个执行简单操作的按钮 mailto:info@example.com
和 运行 到一个问题中:当我单击该按钮时,我被带到 Cloudflare“电子邮件保护”页面,并显示消息“您无法访问此电子邮件地址 example.com".
这是出于一个简单的原因 - 我的浏览器(任何现代浏览器都会出现这种情况)不会从 Cloudflare 加载 email-decode.min.js
脚本。反过来,这是由于 Google Sites 使用 CSP >= v2 并且 CSP 指令的配置方式不允许从 Cloudflare 加载脚本。
根据 Cloudflare 文档,为了使用 Scrape Shield you need to update CSP headers 如下:
script-src 'self' 'unsafe-inline'
这是新的 Google Sites CSP header 的样子:
base-uri 'self';
object-src 'none';
report-uri /_/view/cspreport;
script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval';
worker-src 'self';
frame-ancestors https://google-admin.corp.google.com/
* nonce-<base64-value>
随每个请求更新。
加载包含电子邮件的页面时,我在浏览器控制台中看到以下错误:
Refused to load the script 'https://example.com/cdn-cgi/scripts/6d6ddgh8/cloudflare-static/email-decode.min.js' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
我不确定原因,但由于以下两个原因之一,脚本无法加载:
- 源
'self'
没有为script-src
指令设置(我不认为是这种情况)。 - 源
'unsafe-inline'
被忽略,因为存在加密随机数。
无论如何都行不通。我看到两个解决方案,但我不知道如何实现它们:
- 对于第一个原因(尽管我不认为是这种情况),如果 Google 将源代码
'self'
添加到script-src
指令中,或者如果我有能力定制这个 header 我会自己做。 - 对于第二个原因,如果 Cloudflare 在请求站点时读取 Google 服务器 returns 的
'nonce-<base64-value>'
并将其添加到其脚本中,则可以解决此问题。
如果有人能分享这个问题的解决方案,将不胜感激。
所以我发现原因是 script-src
指令中缺少 'self'
源。
我找到了一个允许在请求/响应中替换 header 的工作人员 forum thread that suggests using Cloudflare Workers to change the required data in a request / response on the fly. I also found a ready-made example code。
受到这个想法的启发,鉴于 Cloudflare 每天免费提供 100,000 个请求,我编写并部署了一个更改服务器响应 header 的工作代码,实际上,它更新了 script-src
指令在 content-security-policy
header 中,用变量 sources
.
我的问题已解决,现在正在加载 Cloudflare 脚本并且按钮可以使用。
* 我不保证代码质量,但它确实有效。代码可以变得更加通用,但我没有时间。
这是我的工人代码:
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
const sources = ["'self'"]
/**
* The function to update a CSP directive with new sources.
* @param {string} directive CSP directive.
* @param {string[]} sources Sources to add to the directive.
* @return {string} Updated CSP directive.
*/
function updateDirective(directive, sources) {
for (let i = 0; i < sources.length; i++) {
if (!directive.toLowerCase().includes(sources[i])) {
directive = directive.concat(" ", sources[i])
}
}
return directive
}
/**
* The function to update the Content-Security-Policy header.
* @param {string} header The Content-Security-Policy header.
* @param {string} directive The Content-Security-Policy directive whose sources need to be updated.
* @param {string} sources Sources to add to the directive.
* @return {string} Updated Content-Security-Policy header.
*/
function updateHeader(header, directive, sources) {
let sourceHeader = header.split(';')
let updatedHeader = []
for (let i = 0; i < sourceHeader.length; i++) {
if (sourceHeader[i].includes(directive)) {
updatedHeader.push(updateDirective(sourceHeader[i], sources))
} else {
updatedHeader.push(sourceHeader[i])
}
}
return updatedHeader.join(";")
}
async function handleRequest(request) {
let response = await fetch(request)
response = new Response(response.body, response)
response.headers.set('content-security-policy',
updateHeader(response.headers.get('content-security-policy'), "script-src", sources))
return response
}