feat: 增强国际化支持与安全头配置

- 在 .env.example 中新增 i18next 相关配置项以支持多语言功能
- 在 next.config.ts 中添加安全头配置以支持 iframe 嵌入
- 更新 Providers 组件以引入 i18n 配置
- 在 PlayerAppShell 中集成 LanguageSwitcher 组件以实现语言切换功能
- 优化 HallWalletStrip 组件的网络状态管理逻辑
- 更新多个组件以支持国际化文本
This commit is contained in:
2026-05-13 17:53:56 +08:00
parent c8f8f90515
commit 587a6ad66c
32 changed files with 2126 additions and 436 deletions

View File

109
src/lib/csp-config.ts Normal file
View File

@@ -0,0 +1,109 @@
/**
* Content Security Policy (CSP) 配置
*
* 支持 iframe 嵌入场景,允许主站加载彩票系统
*/
// 允许的主站来源
const ALLOWED_PARENT_ORIGINS: string[] = [
process.env.NEXT_PUBLIC_MAIN_SITE_URL,
process.env.NEXT_PUBLIC_PARENT_ORIGIN,
// 开发环境
"http://localhost:3001",
"http://127.0.0.1:3001",
// 生产环境应从环境变量读取
].filter((o): o is string => Boolean(o));
/**
* 生成 CSP 指令字符串
*/
export function generateCSP(): string {
const directives: Record<string, string[]> = {
// 默认只允许同源
"default-src": ["'self'"],
// 脚本允许同源和内联Next.js 需要)
"script-src": ["'self'", "'unsafe-inline'", "'unsafe-eval'"],
// 样式允许同源和内联
"style-src": ["'self'", "'unsafe-inline'"],
// 图片允许同源、data URL 和 blob
"img-src": ["'self'", "data:", "blob:"],
// 字体允许同源
"font-src": ["'self'"],
// 连接允许同源和 API 域名
"connect-src": [
"'self'",
process.env.NEXT_PUBLIC_API_URL || "",
// WebSocket 连接
"ws:",
"wss:",
].filter(Boolean),
// 媒体允许同源和 blob
"media-src": ["'self'", "blob:"],
// 对象不允许
"object-src": ["'none'"],
// 框架允许同源和指定父站
"frame-src": ["'self'", ...ALLOWED_PARENT_ORIGINS],
// 允许被嵌入到指定父站
"frame-ancestors": ["'self'", ...ALLOWED_PARENT_ORIGINS],
// 表单提交允许同源
"form-action": ["'self'"],
// 不升级 HTTPS
"upgrade-insecure-requests": [],
};
// 构建 CSP 字符串
return Object.entries(directives)
.map(([key, values]) => {
if (values.length === 0) return key;
return `${key} ${values.join(" ")}`;
})
.join("; ");
}
/**
* 检测是否允许被 iframe 嵌入
* @param parentOrigin 父窗口来源
*/
export function isAllowedParent(parentOrigin: string): boolean {
if (ALLOWED_PARENT_ORIGINS.length === 0) return true; // 未配置时允许所有
return ALLOWED_PARENT_ORIGINS.some(
(origin) => origin && parentOrigin.startsWith(origin),
);
}
/**
* 安全头配置(用于 next.config.ts
*/
export const securityHeaders = [
{
key: "Content-Security-Policy",
value: generateCSP(),
},
{
key: "X-Frame-Options",
value: "SAMEORIGIN", // 允许同源,通过 CSP frame-ancestors 控制跨域
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Referrer-Policy",
value: "strict-origin-when-cross-origin",
},
{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=()",
},
];