mirror of
https://github.com/Silentely/eSIM-Tools.git
synced 2026-09-03 06:24:20 +08:00
feat(security): 更新 Content-Security-Policy 策略配置
新增对 Google Analytics、Google Tag Manager 和 Cloudflare Turnstile 的支持, 同时调整 frame-src 允许加载特定域名内容。此变更应用于多个页面的 CSP 设置, 包括 index.html、giffgaff 和 simyo 相关页面,提升安全性与功能兼容性。 fix(turnstile): 改进 Cloudflare Turnstile 初始化逻辑 增强 widget 加载稳定性并优化 token 刷新机制,增加错误处理和状态管理, 防止重复执行并适配浏览器可见性变化。提取独立脚本确保 CSP 兼容性, 避免内联代码触发安全策略限制。 feat(i18n): 实现页脚组件国际化支持 为 copyright 文本、GitHub 链接及容器添加多语言切换能力, 引入翻译键值绑定与动态更新机制,并完善中英文对照文本定义。 refactor(footer): 抽离页脚国际化相关逻辑 将原有静态文本生成改为参数化解析方式,分离品牌名称与年份范围计算逻辑, 便于后续扩展更多本地化字段与样式控制选项。 chore(scripts): 创建首页专用 i18n 初始化模块 消除主页中的内联 JavaScript 脚本片段,将其封装成外部可引用的 ES Module, 解决潜在的内容安全策略冲突问题,提高代码整洁度和维护性。
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="eSIM 工具集,支持 Giffgaff 与 Simyo 的 eSIM 申请与管理、二维码生成及验证码处理。">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data:; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com; img-src 'self' data: https:; frame-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.googletagmanager.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data:; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google-analytics.com https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com;">
|
||||
<title>eSIM Tools - Giffgaff & Simyo</title>
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<meta name="theme-color" content="#6366f1">
|
||||
@@ -357,10 +357,7 @@
|
||||
<script type="module" src="/src/js/bootstrap-footer.js"></script>
|
||||
|
||||
<!-- 国际化初始化 -->
|
||||
<script type="module">
|
||||
import { initI18n } from '/src/js/modules/i18n.js';
|
||||
initI18n('home');
|
||||
</script>
|
||||
<script type="module" src="/src/js/init-home-i18n.js"></script>
|
||||
|
||||
|
||||
<!-- 性能优化脚本 -->
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<link rel="preconnect" href="https://api.giffgaff.com" crossorigin>
|
||||
<link rel="preconnect" href="https://id.giffgaff.com" crossorigin>
|
||||
<link rel="preconnect" href="https://publicapi.giffgaff.com" crossorigin>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com; img-src 'self' data: https:; frame-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google-analytics.com https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com;">
|
||||
<title>Giffgaff eSIM 申请工具</title>
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<meta name="theme-color" content="#ffcc00">
|
||||
@@ -3648,15 +3648,32 @@
|
||||
try {
|
||||
if (!window.turnstile || !siteKey) { setTimeout(boot, 300); return; }
|
||||
var c = document.createElement('div');
|
||||
c.style.display = 'none';
|
||||
c.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(c);
|
||||
var isExecuting = false;
|
||||
var hasExecuted = false;
|
||||
var markIdle = function() { isExecuting = false; };
|
||||
var exec = function() {
|
||||
if (!window.turnstile || isExecuting) { return; }
|
||||
isExecuting = true;
|
||||
if (hasExecuted) { try { window.turnstile.reset(id); } catch (_) {} }
|
||||
hasExecuted = true;
|
||||
try { window.turnstile.execute(id); } catch (e) { markIdle(); }
|
||||
};
|
||||
var id = window.turnstile.render(c, {
|
||||
sitekey: siteKey,
|
||||
size: 'invisible',
|
||||
callback: function (token) { window.__cfTurnstileToken = token; }
|
||||
callback: function (token) { window.__cfTurnstileToken = token; markIdle(); },
|
||||
'error-callback': markIdle,
|
||||
'timeout-callback': markIdle,
|
||||
'expired-callback': function () { markIdle(); exec(); }
|
||||
});
|
||||
var exec = function() { try { window.turnstile.execute(id); } catch (e) {} };
|
||||
exec();
|
||||
setInterval(exec, 110000);
|
||||
setInterval(function () {
|
||||
if (document.visibilityState === 'hidden') { return; }
|
||||
exec();
|
||||
}, 110000);
|
||||
} catch (e) { setTimeout(boot, 500); }
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<link rel="preconnect" href="https://publicapi.giffgaff.com" crossorigin>
|
||||
|
||||
<!-- CSP策略 -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google-analytics.com https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com;">
|
||||
|
||||
<title>Giffgaff eSIM 申请工具</title>
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
@@ -764,15 +764,32 @@
|
||||
try {
|
||||
if (!window.turnstile || !siteKey) { setTimeout(boot, 300); return; }
|
||||
var c = document.createElement('div');
|
||||
c.style.display = 'none';
|
||||
c.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(c);
|
||||
var isExecuting = false;
|
||||
var hasExecuted = false;
|
||||
var markIdle = function() { isExecuting = false; };
|
||||
var exec = function() {
|
||||
if (!window.turnstile || isExecuting) { return; }
|
||||
isExecuting = true;
|
||||
if (hasExecuted) { try { window.turnstile.reset(id); } catch (_) {} }
|
||||
hasExecuted = true;
|
||||
try { window.turnstile.execute(id); } catch (e) { markIdle(); }
|
||||
};
|
||||
var id = window.turnstile.render(c, {
|
||||
sitekey: siteKey,
|
||||
size: 'invisible',
|
||||
callback: function (token) { window.__cfTurnstileToken = token; }
|
||||
callback: function (token) { window.__cfTurnstileToken = token; markIdle(); },
|
||||
'error-callback': markIdle,
|
||||
'timeout-callback': markIdle,
|
||||
'expired-callback': function () { markIdle(); exec(); }
|
||||
});
|
||||
var exec = function() { try { window.turnstile.execute(id); } catch (e) {} };
|
||||
exec();
|
||||
setInterval(exec, 110000);
|
||||
setInterval(function () {
|
||||
if (document.visibilityState === 'hidden') { return; }
|
||||
exec();
|
||||
}, 110000);
|
||||
} catch (e) { setTimeout(boot, 500); }
|
||||
}
|
||||
if (document.readyState === 'loading') {
|
||||
|
||||
4
src/js/init-home-i18n.js
Normal file
4
src/js/init-home-i18n.js
Normal file
@@ -0,0 +1,4 @@
|
||||
// 首页国际化入口脚本:避免内联脚本触发 CSP 限制
|
||||
import { initI18n } from './modules/i18n.js';
|
||||
|
||||
initI18n('home');
|
||||
@@ -18,43 +18,107 @@ window.TURNSTILE_SITE_KEY = (typeof process !== 'undefined' && process.env && pr
|
||||
? process.env.TURNSTILE_SITE_KEY
|
||||
: '0x4AAAAAABqjeVscZAiqB11B';
|
||||
|
||||
|
||||
if (window.TURNSTILE_SITE_KEY) {
|
||||
const s = document.createElement('script');
|
||||
s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
|
||||
s.async = true;
|
||||
s.defer = true;
|
||||
document.head.appendChild(s);
|
||||
const ensureLoaderScript = () => {
|
||||
if (window.turnstile) {
|
||||
return true;
|
||||
}
|
||||
const selector = 'script[src="https://challenges.cloudflare.com/turnstile/v0/api.js"]';
|
||||
const existing = document.querySelector(selector);
|
||||
if (existing) {
|
||||
if (!existing.dataset.turnstileLoader) {
|
||||
existing.dataset.turnstileLoader = 'true';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.dataset.turnstileLoader = 'true';
|
||||
document.head.appendChild(script);
|
||||
return false;
|
||||
};
|
||||
|
||||
// 定义回调,保存 token 供 /bff/* 请求使用
|
||||
window.onTurnstileDone = (token) => {
|
||||
window.__cfTurnstileToken = token;
|
||||
};
|
||||
|
||||
// 初始化不可见 Turnstile 并立即执行获取 token
|
||||
let widgetId = null;
|
||||
let hasExecuted = false;
|
||||
let executing = false;
|
||||
|
||||
const markIdle = () => { executing = false; };
|
||||
|
||||
const handleToken = (token) => {
|
||||
window.__cfTurnstileToken = token;
|
||||
markIdle();
|
||||
};
|
||||
|
||||
const runExecute = () => {
|
||||
if (!window.turnstile || widgetId == null || executing) {
|
||||
return;
|
||||
}
|
||||
executing = true;
|
||||
if (hasExecuted) {
|
||||
try { window.turnstile.reset(widgetId); } catch (_) {}
|
||||
}
|
||||
hasExecuted = true;
|
||||
try {
|
||||
window.turnstile.execute(widgetId);
|
||||
} catch (_) {
|
||||
markIdle();
|
||||
}
|
||||
};
|
||||
|
||||
const initTurnstile = () => {
|
||||
if (!window.turnstile) {
|
||||
setTimeout(initTurnstile, 300);
|
||||
return;
|
||||
}
|
||||
const container = document.createElement('div');
|
||||
container.style.display = 'none';
|
||||
container.setAttribute('aria-hidden', 'true');
|
||||
document.body.appendChild(container);
|
||||
const widgetId = window.turnstile.render(container, {
|
||||
widgetId = window.turnstile.render(container, {
|
||||
sitekey: window.TURNSTILE_SITE_KEY,
|
||||
size: 'invisible',
|
||||
callback: (token) => {
|
||||
window.__cfTurnstileToken = token;
|
||||
callback: handleToken,
|
||||
'error-callback': markIdle,
|
||||
'timeout-callback': markIdle,
|
||||
'expired-callback': () => {
|
||||
markIdle();
|
||||
runExecute();
|
||||
}
|
||||
});
|
||||
// 主动执行以获取 token(并定期刷新)
|
||||
const exec = () => { try { window.turnstile.execute(widgetId); } catch (_) {} };
|
||||
exec();
|
||||
setInterval(exec, 110000); // 约每110秒刷新一次
|
||||
runExecute();
|
||||
setInterval(() => {
|
||||
if (document.visibilityState === 'hidden') return;
|
||||
runExecute();
|
||||
}, 110000);
|
||||
};
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initTurnstile);
|
||||
const boot = () => {
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initTurnstile, { once: true });
|
||||
} else {
|
||||
initTurnstile();
|
||||
}
|
||||
};
|
||||
|
||||
if (ensureLoaderScript()) {
|
||||
boot();
|
||||
} else {
|
||||
initTurnstile();
|
||||
const waitForScript = () => {
|
||||
if (window.turnstile) {
|
||||
boot();
|
||||
return;
|
||||
}
|
||||
setTimeout(waitForScript, 150);
|
||||
};
|
||||
waitForScript();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,65 @@
|
||||
// 统一页脚组件:自动注入到页面底部
|
||||
import './config.js';
|
||||
import { t, onLocaleChange } from './i18n.js';
|
||||
|
||||
function getCopyrightText() {
|
||||
function resolveFooterParams() {
|
||||
const currentYear = new Date().getFullYear();
|
||||
try {
|
||||
const cfg = window.__APP_CONFIG__ || {};
|
||||
const brand = cfg.brand || 'eSIM Tools';
|
||||
const since = Number(cfg.since) || new Date().getFullYear();
|
||||
const current = new Date().getFullYear();
|
||||
const yearText = since && since < current ? `${since}–${current}` : `${current}`;
|
||||
return `© ${yearText} ${brand}. 保留所有权利。`;
|
||||
const since = Number(cfg.since) || currentYear;
|
||||
const yearRange = since && since < currentYear ? `${since}–${currentYear}` : `${currentYear}`;
|
||||
return { brand, yearRange };
|
||||
} catch (_) {
|
||||
const current = new Date().getFullYear();
|
||||
return `© ${current} eSIM Tools. 保留所有权利。`;
|
||||
return { brand: 'eSIM Tools', yearRange: `${currentYear}` };
|
||||
}
|
||||
}
|
||||
|
||||
function translateOrFallback(key, fallback, params) {
|
||||
try {
|
||||
const value = params ? t(key, params) : t(key);
|
||||
if (typeof value === 'string' && value !== key) {
|
||||
return value;
|
||||
}
|
||||
} catch (_) {}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function bindGithubLink(link) {
|
||||
const apply = () => {
|
||||
const aria = translateOrFallback('footer.github.ariaLabel', '在 GitHub 上查看源码');
|
||||
link.setAttribute('aria-label', aria);
|
||||
};
|
||||
apply();
|
||||
onLocaleChange(apply);
|
||||
}
|
||||
|
||||
function bindContainerAria(container) {
|
||||
const apply = () => {
|
||||
const aria = translateOrFallback('footer.container.ariaLabel', '版权与声明');
|
||||
container.setAttribute('aria-label', aria);
|
||||
};
|
||||
apply();
|
||||
onLocaleChange(apply);
|
||||
}
|
||||
|
||||
function bindCopyright(span, options = {}) {
|
||||
const custom = typeof options.text === 'string' ? options.text.trim() : '';
|
||||
if (custom) {
|
||||
span.textContent = custom;
|
||||
return;
|
||||
}
|
||||
|
||||
const apply = () => {
|
||||
const params = resolveFooterParams();
|
||||
const fallback = `© ${params.yearRange} ${params.brand}. 保留所有权利。`;
|
||||
span.textContent = translateOrFallback('footer.copyright', fallback, params);
|
||||
};
|
||||
|
||||
apply();
|
||||
onLocaleChange(apply);
|
||||
}
|
||||
|
||||
export function injectFooter(options = {}) {
|
||||
if (document.querySelector('footer[data-component="app-footer"]')) return;
|
||||
|
||||
@@ -30,38 +75,38 @@ export function injectFooter(options = {}) {
|
||||
div.style.justifyContent = 'center';
|
||||
div.style.gap = '12px';
|
||||
div.style.marginTop = '8px';
|
||||
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.textContent = options.text || getCopyrightText();
|
||||
|
||||
bindCopyright(span, options);
|
||||
|
||||
const githubLink = document.createElement('a');
|
||||
githubLink.href = 'https://github.com/Silentely/eSIM-Tools';
|
||||
githubLink.target = '_blank';
|
||||
githubLink.rel = 'noopener noreferrer';
|
||||
githubLink.setAttribute('aria-label', '在 GitHub 上查看源码');
|
||||
githubLink.style.display = 'flex';
|
||||
githubLink.style.alignItems = 'center';
|
||||
githubLink.style.justifyContent = 'center';
|
||||
githubLink.style.color = '#6b7280';
|
||||
githubLink.style.textDecoration = 'none';
|
||||
githubLink.style.transition = 'color 0.2s ease';
|
||||
|
||||
|
||||
const githubIcon = document.createElement('i');
|
||||
githubIcon.className = 'fab fa-github';
|
||||
githubIcon.style.fontSize = '18px';
|
||||
|
||||
|
||||
githubLink.addEventListener('mouseenter', () => {
|
||||
githubLink.style.color = '#1f2937';
|
||||
});
|
||||
|
||||
|
||||
githubLink.addEventListener('mouseleave', () => {
|
||||
githubLink.style.color = '#6b7280';
|
||||
});
|
||||
|
||||
|
||||
githubLink.appendChild(githubIcon);
|
||||
bindGithubLink(githubLink);
|
||||
div.appendChild(span);
|
||||
div.appendChild(githubLink);
|
||||
|
||||
|
||||
return div;
|
||||
};
|
||||
|
||||
@@ -75,7 +120,6 @@ export function injectFooter(options = {}) {
|
||||
// 情形 2 / 3:新建组件化 footer
|
||||
const container = document.createElement('footer');
|
||||
container.setAttribute('role', 'contentinfo');
|
||||
container.setAttribute('aria-label', '版权与声明');
|
||||
container.setAttribute('data-component', 'app-footer');
|
||||
container.style.cssText = [
|
||||
'margin-top:40px',
|
||||
@@ -86,6 +130,7 @@ export function injectFooter(options = {}) {
|
||||
'font-size:14px'
|
||||
].join(';');
|
||||
container.appendChild(createCopyrightNode());
|
||||
bindContainerAria(container);
|
||||
|
||||
const pickTarget = () => {
|
||||
return (
|
||||
@@ -108,4 +153,4 @@ export function autoInjectFooter() {
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,6 +232,9 @@ export const TRANSLATIONS = {
|
||||
'home.simyo.features.confirm': '安装确认功能',
|
||||
'home.simyo.cta': '使用 Simyo 工具',
|
||||
'home.footer.html': '<i class=\"fas fa-info-circle me-2\" aria-hidden=\"true\"></i> 本工具仅供个人使用,请遵守相关服务条款。<br><i class=\"fas fa-shield-alt me-2\" aria-hidden=\"true\"></i> 所有数据处理均在本地进行,保护您的隐私安全。',
|
||||
'footer.container.ariaLabel': '版权与声明',
|
||||
'footer.github.ariaLabel': '在 GitHub 上查看源码',
|
||||
'footer.copyright': '© {yearRange} {brand}。保留所有权利。',
|
||||
|
||||
'giffgaff.meta.title': 'Giffgaff eSIM 申请工具',
|
||||
'giffgaff.meta.description': 'Giffgaff eSIM 工具,支持 OAuth 登录、MFA 验证、二维码生成与设备更换。',
|
||||
@@ -454,6 +457,9 @@ export const TRANSLATIONS = {
|
||||
'home.simyo.features.confirm': 'Installation confirmation',
|
||||
'home.simyo.cta': 'Launch Simyo tool',
|
||||
'home.footer.html': '<i class=\"fas fa-info-circle me-2\" aria-hidden=\"true\"></i> For personal use only. Please follow the related terms of service.<br><i class=\"fas fa-shield-alt me-2\" aria-hidden=\"true\"></i> All data processing happens locally to keep your privacy safe.',
|
||||
'footer.container.ariaLabel': 'Copyright and disclaimer',
|
||||
'footer.github.ariaLabel': 'View source on GitHub',
|
||||
'footer.copyright': '© {yearRange} {brand}. All rights reserved.',
|
||||
|
||||
'giffgaff.meta.title': 'Giffgaff eSIM Application Tool',
|
||||
'giffgaff.meta.description': 'Giffgaff eSIM toolkit covering OAuth login, MFA verification, QR generation, and device change workflows.',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com; img-src 'self' data: https:; frame-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google-analytics.com https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://api.giffgaff.com https://id.giffgaff.com https://publicapi.giffgaff.com https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com;">
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
|
||||
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
|
||||
<title>Simyo NL eSIM 申请工具</title>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<link rel="preconnect" href="https://appapi.simyo.nl" crossorigin>
|
||||
|
||||
<!-- CSP策略 -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl; img-src 'self' data: https:; frame-src 'none';">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; font-src 'self' data: https://cdnjs.cloudflare.com; connect-src 'self' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com https://www.google-analytics.com https://www.googletagmanager.com https://qrcode.show https://api.qrserver.com https://appapi.simyo.nl https://challenges.cloudflare.com; img-src 'self' data: https:; frame-src 'self' https://challenges.cloudflare.com;">
|
||||
|
||||
<title>Simyo NL eSIM 申请工具</title>
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
|
||||
Reference in New Issue
Block a user