前端面试必看:CSP内容安全策略
本文专为前端面试梳理,白话讲解+CSP实操+高频真题,复盘、发文两用,看完吃透CSP核心考点。
一、基础认知:一句话吃透CSP
CSP(Content-Security-Policy)即内容安全策略,是浏览器提供的白名单安全机制,通过制定资源加载规则,限制页面可执行/加载的脚本、样式、图片等资源,从源头抵御XSS攻击、数据注入等安全风险,是前端必备安全知识点。
核心本质:不信任任何外部未知资源,只放行明确授权的内容,堵死恶意代码执行路径
二、核心作用:解决什么问题?
- 主要防御目标:XSS攻击(存储型、反射型),杜绝恶意注入的JS脚本执行
- 限制非法资源加载:禁止未经授权的第三方脚本、字体、iframe、插件等
- 防范数据窃取、页面篡改、点击劫持等衍生安全问题
- 补充说明:CSP是安全增强层,无法100%杜绝所有XSS(如DOM型XSS、CSP绕过漏洞),但能大幅降低风险
三、两种配置方式(面试必答)
1. HTTP响应头配置(生产推荐)
通过服务器(Nginx、Node、Apache)设置响应头,功能最全、优先级最高,支持所有CSP指令。
# Nginx 配置 CSP 响应头(生产环境推荐)
# always:确保所有响应(如404/500)都携带CSP头
add_header Content-Security-Policy "
default-src 'self';# 默认仅允许同域资源
script-src 'self';# JS脚本仅允许加载同域
object-src 'none' # 禁止所有插件(Flash/Java等)
" always;
// Node/Express中间件配置
const express = require('express');
const app = express();
// 全局CSP响应头
app.use((req, res, next) => {
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self'; object-src 'none'"
);
next();
});
app.listen(3000, () => console.log('服务启动成功'));
2. Meta标签配置(纯前端)
直接写入HTML头部,无需修改服务器,适合静态页面;局限性:不支持frame-ancestors、report-uri等指令。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CSP配置示例</title>
<!-- 纯前端CSP配置 -->
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' data:
">
</head>
<body>
<h1>CSP页面演示</h1>
</body>
</html>
四、高频指令&关键字(必背表格)
1. 核心指令(控制不同资源)
| 指令 | 作用 |
|---|---|
| default-src | 默认规则,所有未单独配置的资源均遵循此指令 |
| script-src | 控制JS脚本、内联script、eval执行 |
| style-src | 控制CSS样式、内联样式 |
| img-src | 控制图片、图标资源加载 |
| connect-src | 控制fetch/ajax/websocket等网络请求 |
| frame-src | 控制iframe嵌套页面 |
| object-src | 控制Flash、插件等,推荐设为none |
| frame-ancestors | 控制页面是否允许被嵌套,防点击劫持 |
2. 关键配置值(高频考点)
- 'self' :仅允许同域名、同协议、同端口的资源,最常用
- 'none' :禁止所有相关资源,安全性最高
- 'unsafe-inline' :允许内联脚本/样式(不推荐,XSS主要利用点)
- 'unsafe-eval' :允许eval、new Function等动态执行代码(高危)
- 具体域名:如cdn.baidu.com,放行指定第三方资源
- data::允许base64格式资源(如图片、字体)
五、安全进阶:nonce与hash(替代unsafe-inline)
业务必须使用内联脚本时,摒弃unsafe-inline,采用更安全的方式,掘金代码块演示如下:
1. nonce(随机数)
服务端每次生成唯一随机字符串,CSP白名单绑定该nonce,仅携带对应nonce的内联脚本可执行。
# 响应头配置nonce
add_header Content-Security-Policy "script-src 'nonce-2025csp-random-key';";
<!-- 合法内联脚本,必须携带对应nonce -->
<script nonce="2025csp-random-key">
console.log('CSP允许的内联脚本执行')
</script>
2. hash(哈希值)
计算内联脚本内容的SHA哈希,将哈希值加入白名单,仅匹配哈希的脚本可执行。
# 配置哈希值放行内联脚本
Content-Security-Policy "script-src 'sha256-abcdefghijklmn1234567890';"
六、调试技巧:Report-Only模式
上线前必用,只上报违规、不拦截资源,避免配置错误导致页面崩溃,控制台可查看所有违规资源。
# 调试模式:仅上报不拦截
add_header Content-Security-Policy-Report-Only "default-src 'self';";
<!-- meta标签调试写法 -->
<meta http-equiv="Content-Security-Policy-Report-Only" content="default-src 'self'">
七、面试高频问答(直接背诵)
1. CSP为什么能防XSS?
XSS核心是注入恶意内联/外部脚本,CSP默认禁止内联脚本、限制脚本来源,攻击者注入的代码不在白名单内,浏览器会直接拦截不执行,从根源阻断攻击。
2. meta标签和HTTP响应头的区别?
HTTP响应头功能完整、优先级更高,支持所有指令,适合生产环境;meta标签纯前端配置、便捷但有指令限制,适合静态页面调试。
3. 为什么不推荐用unsafe-inline?
开启后允许任意内联脚本执行,XSS攻击者可直接注入恶意内联代码,完全失去CSP的防护意义,业务需内联脚本时优先用nonce/hash替代。
4. 项目配置CSP后页面异常,怎么排查?
第一步打开浏览器控制台,查看CSP违规报错;第二步切换Report-Only模式定位问题资源;第三步将可信资源加入对应白名单;第四步验证无误后正式启用CSP。
5. CSP和X-XSS-Protection的区别?
X-XSS-Protection是浏览器基础XSS防护,规则简单、易被绕过;CSP是白名单机制,防护更全面、更灵活,是现代主流安全方案。
八、生产标准配置(直接复制复用)
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{{随机值}}';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
connect-src 'self' https://api.xxx.com;
object-src 'none';
frame-ancestors 'self';
frame-src 'none';
面试收尾金句:CSP通过白名单机制严控资源加载,是前端防御XSS的核心手段,生产环境优先用响应头配置,结合nonce提升安全性,上线前用Report-Only调试。