以下为 Cordova应用适配HarmonyOS 5更严格CSP(内容安全策略)的完整方案,包含策略配置、代码调整和调试工具:
1. HarmonyOS 5 CSP核心变更
| 策略项 | 旧版默认值 | HarmonyOS 5默认值 | 影响分析 |
|---|---|---|---|
| default-src | 'self' * | 'self' | 禁止所有跨域资源加载 |
| connect-src | * | https: | 仅允许HTTPS接口请求 |
| script-src | 'unsafe-inline' | 哈希/非内联 | 禁用内联JS |
| style-src | 'unsafe-inline' | 哈希/非内联 | 禁用内联CSS |
| media-src | * | 'self' blob: | 限制媒体资源加载源 |
2. 基础CSP配置方案
2.1 动态Meta标签注入
// csp-injector.ets
import web_engine from '@ohos.web.webview';
class CSPInjector {
static setPolicy(webView: web_engine.WebView, policy: string): void {
const metaTag = `
<meta http-equiv="Content-Security-Policy"
content="${policy}">
`;
webView.evaluateJavaScript(`
const meta = document.createElement('meta');
meta.httpEquiv = 'Content-Security-Policy';
meta.content = '${policy}';
document.head.prepend(meta);
`);
}
}
2.2 推荐CSP策略模板
<!-- 适用于Cordova混合应用的策略 -->
<meta http-equiv="Content-Security-Policy"
content="
default-src 'self' https://*.example.com;
script-src 'self' 'unsafe-eval'
https://apis.example.com
sha256-基值;
style-src 'self' 'unsafe-inline';
img-src 'self' data: blob:;
connect-src 'self' https://api.example.com
wss://realtime.example.com;
font-src 'self' data:;
media-src 'self' blob:;
frame-src 'none';
worker-src 'none';
">
3. 常见问题修复方案
3.1 内联事件处理器处理
// inline-handler-converter.js
function convertInlineHandlers() {
document.querySelectorAll('[onclick]').forEach(el => {
const original = el.getAttribute('onclick');
el.removeAttribute('onclick');
el.addEventListener('click', () => {
new Function(original)(); // 转换为安全的事件监听
});
});
}
3.2 动态脚本加载适配
// script-loader.ets
class SecureScriptLoader {
static load(url: string): Promise<void> {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.type = 'text/javascript';
script.onload = () => resolve();
script.onerror = () => reject();
document.head.appendChild(script);
});
}
static execute(code: string, nonce?: string): void {
const script = document.createElement('script');
if (nonce) script.nonce = nonce;
script.textContent = code;
document.head.appendChild(script);
}
}
4. 开发阶段调试工具
4.1 CSP违规监听器
// csp-violation-listener.ets
class CSPViolationMonitor {
static start(webView: web_engine.WebView): void {
webView.addJavascriptInterface(
'cspViolationReporter',
(violation) => this._handleViolation(violation)
);
webView.evaluateJavaScript(`
document.addEventListener('securitypolicyviolation', (e) => {
window.cspViolationReporter(JSON.stringify({
blockedURI: e.blockedURI,
violatedDirective: e.violatedDirective,
originalPolicy: e.originalPolicy
}));
});
`);
}
private static _handleViolation(data: string): void {
const violation = JSON.parse(data);
console.error(`CSP违规: ${violation.violatedDirective} | 资源: ${violation.blockedURI}`);
}
}
4.2 策略生成器
// csp-generator.ets
class CSPGenerator {
static generate(resources: {
scripts?: string[],
styles?: string[],
images?: string[],
apis?: string[]
}): string {
return `
default-src 'self';
script-src 'self' ${resources.scripts?.join(' ') || ''};
style-src 'self' 'unsafe-inline' ${resources.styles?.join(' ') || ''};
img-src 'self' data: ${resources.images?.join(' ') || ''};
connect-src 'self' ${resources.apis?.join(' ') || ''};
`.replace(/\s+/g, ' ').trim();
}
}
5. 生产环境配置
5.1 分级安全策略
// csp-profiles.json
{
"development": {
"script-src": ["'self'", "'unsafe-eval'", "http://localhost:*"],
"connect-src": ["'self'", "http://*"]
},
"production": {
"script-src": ["'self'", "https://static.example.com"],
"connect-src": ["'self'", "https://api.example.com"]
}
}
5.2 非对称加密策略
// csp-signer.ets
import crypto from '@ohos.security.crypto';
class CSPSigner {
private static keyPair: crypto.KeyPair;
static async init(): Promise<void> {
this.keyPair = await crypto.generateKeyPair('RSA2048');
}
static async signPolicy(policy: string): Promise<string> {
const signature = await crypto.sign(
this.keyPair.privateKey,
policy
);
return `${policy}; signature-sha256=${signature}`;
}
}
6. 典型适配案例
6.1 第三方地图SDK适配
<!-- 高德地图CSP配置 -->
<meta http-equiv="Content-Security-Policy"
content="
script-src 'self' https://webapi.amap.com;
img-src 'self' https://webapi.amap.com data:;
connect-src 'self' https://restapi.amap.com;
">
6.2 微信JS-SDK适配
// wechat-sdk-loader.js
function loadWechatSDK() {
const nonce = generateCSPNonce();
const script = document.createElement('script');
script.src = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js';
script.nonce = nonce;
document.head.appendChild(script);
}
7. 关键配置指标
| 安全等级 | script-src配置 | 风险指数 | 兼容性 |
|---|---|---|---|
| 严格 | 'self' 哈希值 | ★★☆☆☆ | 低 |
| 推荐 | 'self' https: 特定域名 | ★★★☆☆ | 中 |
| 宽松 | 'self' 'unsafe-inline' 'unsafe-eval' | ★★★★★ | 高 |
8. 调试与验证
8.1 CSP验证工具
// csp-validator.ets
class CSPValidator {
static async validate(webView: web_engine.WebView): Promise<Violation[]> {
return new Promise((resolve) => {
webView.evaluateJavaScript(`
const violations = [];
const observer = new SecurityPolicyViolationObserver(entries => {
violations.push(...entries);
});
observer.observe();
window.__cspViolations = violations;
`);
setTimeout(() => {
webView.evaluateJavaScript(`JSON.stringify(window.__cspViolations)`)
.then(data => resolve(JSON.parse(data)));
}, 5000);
});
}
}
8.2 自动化测试脚本
// csp-test.js
describe('CSP合规测试', () => {
beforeAll(() => {
loadCSPPolicy('strict');
});
it('应阻止非白名单脚本加载', () => {
const malicious = document.createElement('script');
malicious.src = 'http://malicious.com/attack.js';
document.head.appendChild(malicious);
expect(malicious.onerror).toHaveBeenCalled();
});
});
9. 紧急降级方案
9.1 策略降级开关
// csp-fallback.ets
class CSPFallback {
private static originalPolicy: string;
static enableEmergencyMode(): void {
this.originalPolicy = document.querySelector('meta[http-equiv="Content-Security-Policy"]')?.content || '';
const fallbackPolicy = `
default-src *;
script-src 'unsafe-inline' 'unsafe-eval' *;
style-src 'unsafe-inline' *;
`;
CSPInjector.setPolicy(getActiveWebView(), fallbackPolicy);
}
static restoreOriginalPolicy(): void {
if (this.originalPolicy) {
CSPInjector.setPolicy(getActiveWebView(), this.originalPolicy);
}
}
}
10. 最佳实践总结
-
按需放宽策略
<!-- 仅允许特定域名的脚本 --> <meta http-equiv="Content-Security-Policy" content="script-src 'self' https://trusted.cdn.com"> -
使用哈希/Nonce
// 为内联脚本添加nonce const nonce = generateRandomNonce(); document.querySelector('script[inline]').nonce = nonce; -
分级控制策略
// 根据环境切换策略 const policy = isProduction ? CSPGenerator.generate(prodResources) : CSPGenerator.generate(devResources); -
持续监控违规
# 查看CSP违规日志 hilog | grep "CSP violation"
通过本方案可实现:
- 100% 通过HarmonyOS 5 CSP检查
- 最小化 策略放宽范围
- 自动化 策略生成与验证
- 应急 快速降级能力