前端安全是企业面试重点、线上项目刚需,核心围绕防攻击、防篡改、数据加密、合规编码四大核心。多数线上安全漏洞均源于XSS、CSRF攻击、不规范编码、明文传输、弱加密算法。本文全覆盖指定考点:XSS/CSRF全方位防御、CSP内容安全策略、encodeURIComponent编码、btoa/atob编解码、SubtleCrypto原生加密接口,搭配可运行源码、攻防案例、工程最佳实践、高频面试题。
一、XSS 跨站脚本攻击(前端最核心安全漏洞)
XSS(Cross-Site Scripting)跨站脚本攻击:攻击者注入恶意JS代码,在用户页面执行,窃取用户信息、劫持页面、植入木马,是前端最高发、最基础的安全漏洞。
1.1 XSS 三种攻击类型
-
存储型XSS(永久型):恶意代码提交到服务端数据库,所有用户访问页面均会触发,危害最大(评论区、发帖功能)
-
反射型XSS(临时型):恶意代码通过URL参数传递,用户点击链接瞬时触发,不存储在服务端(搜索参数、跳转参数)
-
DOM型XSS(纯前端):完全由前端JS解析URL、本地数据触发,服务端无感知,仅前端渲染漏洞
1.2 原生XSS漏洞案例
// 危险写法:直接拼接用户输入,触发DOM型XSS
// 假设url参数:?name=<script>alert('XSS攻击')</script>
const name = new URLSearchParams(location.search).get('name')
document.getElementById('box').innerHTML = name // 直接渲染触发恶意代码
1.3 XSS 全方位防御方案(工程必用)
1. 前端编码转义(基础防御)
对用户输入、动态渲染内容做HTML特殊字符转义,将可执行标签转为纯文本字符。
// XSS转义函数(核心)
function htmlEncode(str) {
if (!str) return ''
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
}
// 安全渲染:转义后再插入DOM
const name = new URLSearchParams(location.search).get('name')
document.getElementById('box').innerText = htmlEncode(name)
2. 杜绝危险API
禁止使用 innerHTML、outerHTML、document\.write 渲染用户动态内容,优先使用 innerText、textContent 纯文本渲染。
3. 高级防御:CSP策略(下文详解)
4. 安全头部:X-XSS-Protection
服务端配置响应头,开启浏览器内置XSS防护:X\-XSS\-Protection: 1; mode=block
二、CSRF 跨站请求伪造与防御
CSRF(Cross-Site Request Forgery)跨站请求伪造:利用用户已登录的Cookie身份,诱导用户在恶意网站向目标网站发起非法请求,实现盗号、篡改信息、恶意下单等操作。
核心本质:浏览器自动携带Cookie,服务端无法区分请求是否为用户自愿发起。
2.1 CSRF 攻击流程
-
用户登录A网站,浏览器保存A网站登录Cookie
-
用户未退出登录,访问恶意B网站
-
B网站自动发起A网站接口请求,浏览器自动携带Cookie
-
A网站校验Cookie通过,执行非法操作
2.2 主流防御方案(企业级)
1. Token 校验(最常用)
登录后下发 CSRF-Token,前端每次请求手动携带Token,服务端校验:Cookie自动携带、Token手动携带,恶意网站无法获取用户Token,彻底杜绝攻击。
2. SameSite Cookie 属性(现代最优)
设置 Cookie 的SameSite=Strict/Lax,禁止跨站点请求携带Cookie,从根源拦截CSRF。
-
Strict:仅同源请求携带Cookie,跨站完全禁止
-
Lax:宽松模式,允许GET导航携带,禁止POST跨站请求
3. 校验 Referer/Origin 请求头
服务端校验请求来源,拒绝非信任域名的跨站请求(适合辅助防御)。
2.3 XSS 与 CSRF 核心区别(面试必考)
-
XSS:窃取用户权限,执行恶意代码,主动攻击,危害更大
-
CSRF:借用用户权限,无法获取用户数据,只能发起请求
-
XSS是代码注入,CSRF是身份冒用
三、CSP 内容安全策略(XSS终极防御)
CSP(Content Security Policy)是浏览器最高级别的安全防护机制,通过白名单限制页面资源加载、脚本执行,从根源禁止恶意代码运行,是防御XSS、代码注入的终极方案。
3.1 核心原理
浏览器默认允许所有资源加载与脚本执行,CSP通过白名单策略,仅允许指定域名、指定类型资源运行,拦截所有未知、内联、eval恶意脚本。
3.2 两种配置方式
1. 服务端响应头配置(推荐、优先级最高)
服务端返回响应头,全局生效,安全性最高
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self'; img-src * data:;
2. HTML meta标签配置
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
3.3 常用核心指令(工程必备)
-
default-src:默认资源白名单,兜底所有资源
-
script-src:脚本白名单,禁止内联脚本、eval(拦截绝大多数XSS)
-
style-src:样式资源白名单
-
img-src:图片、媒体资源白名单
-
connect-src:接口请求、WebSocket白名单
-
'self':允许当前同源域名
3.4 CSP 核心拦截能力
-
禁止内联脚本执行(
\<script\>alert\(\)直接拦截) -
禁止 eval、new Function 动态代码执行
-
禁止加载未知第三方恶意脚本、资源
-
彻底拦截绝大多数XSS注入攻击
四、前端编码API:encodeURI / encodeURIComponent
URL编码是前端数据传输、防乱码、防注入的基础,面试高频考察两个API的区别与使用场景,错误使用会导致参数丢失、接口报错、安全漏洞。
4.1 核心差异与原理
-
encodeURI:用于完整URL编码,仅编码特殊字符,不编码 : / ? # & = 等URL关键符号
-
encodeURIComponent:用于URL参数编码,编码所有特殊字符,包含 : / ? # 等分隔符,是参数传输首选
4.2 实战案例与规范用法
// 1. 完整URL使用 encodeURI
const url = 'https://xxx.com?name=前端测试'
console.log(encodeURI(url))
// 正常保留URL结构,仅编码中文
// 2. URL参数必须使用 encodeURIComponent(标准规范)
const name = 'a&b=123' // 恶意特殊参数
const params = `name=${encodeURIComponent(name)}`
console.log(params)
// 转义&,避免参数被篡改,防止参数注入漏洞
// 对应解码API
// decodeURI() / decodeURIComponent()
4.3 工程硬性规范
-
拼接 URL参数、请求体参数:必须用 encodeURIComponent
-
跳转 完整URL地址:使用 encodeURI
-
禁止混用,避免参数截断、URL解析异常、简单注入漏洞
五、btoa / atob base64 编解码
btoa/atob 是浏览器原生Base64编解码API,无需第三方库,常用于简单数据脱敏、二进制转文本、Token临时编码。
5.1 基础用法
// btoa:字符串 => Base64 编码
const str = 'hello security'
const encodeStr = btoa(str)
console.log('编码结果:', encodeStr)
// atob:Base64 => 字符串 解码
const decodeStr = atob(encodeStr)
console.log('解码结果:', decodeStr)
5.2 核心坑点(高频错题)
btoa 不支持中文、Unicode字符,直接中文编码会报错!
解决方案:先 encodeURIComponent 编码,再 btoa
// 兼容中文的Base64编解码封装
function utf8Btoa(str) {
return btoa(encodeURIComponent(str))
}
function utf8Atob(str) {
return decodeURIComponent(atob(str))
}
// 测试中文
console.log(utf8Btoa('前端安全加密'))
console.log(utf8Atob(utf8Btoa('前端安全加密')))
5.3 重要安全提醒
Base64 只是编码,不是加密! 可直接逆向解码,不能用于密码、私密数据加密,仅用于脱敏、传输格式转换。
六、SubtleCrypto 原生加密接口(Web标准加密)
SubtleCrypto 是浏览器原生、标准、安全的加密API,替代废弃的 window\.crypto,支持 SHA256摘要、AES对称加密、RSA非对称加密,异步执行、安全性高,是前端正规加密方案。
核心特性:异步API、无法逆向破解、支持主流加密算法、符合Web安全规范
6.1 前置规范
-
仅支持 HTTPS / localhost 环境,HTTP普通域名无法使用
-
所有加密操作异步执行,不阻塞主线程
-
支持密钥导出、密钥导入、加盐加密,安全性远超第三方JS加密库
6.2 实战1:SHA-256 哈希摘要(密码加密)
哈希摘要:不可逆加密,常用于密码加密、文件校验
// SHA256 哈希加密
async function sha256Encrypt(str) {
// 字符串转二进制
const encoder = new TextEncoder()
const data = encoder.encode(str)
// 执行哈希摘要
const hash = await crypto.subtle.digest('SHA-256', data)
// 转为16进制字符串
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('')
}
// 测试
sha256Encrypt('123456').then(res => console.log('SHA256加密结果:', res))
6.3 实战2:AES 对称加解密(业务数据加密)
AES对称加密:加密解密密钥一致,适合前端向后端传输私密数据
// 生成AES密钥
async function generateAESKey() {
return await crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 128 },
true,
['encrypt', 'decrypt']
)
}
// AES加密
async function aesEncrypt(key, data) {
const encoder = new TextEncoder()
const encoded = encoder.encode(data)
const iv = crypto.getRandomValues(new Uint8Array(12))
const encrypt = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
encoded
)
return { iv, data: new Uint8Array(encrypt) }
}
// AES解密
async function aesDecrypt(key, iv, data) {
const decrypt = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv },
key,
data
)
return new TextDecoder().decode(decrypt)
}
6.4 工程使用场景
-
用户密码哈希存储(SHA256)
-
敏感参数、手机号、身份证加密传输(AES)
-
文件哈希校验、防篡改校验
-
替代不安全的md5、简单base64明文编码
七、全文核心总结(面试必背)
-
XSS攻击:脚本注入执行,分存储型、反射型、DOM型,防御核心:转义渲染、禁止危险API、CSP策略、头部防护
-
CSRF攻击:跨站身份冒用,利用Cookie自动携带,防御核心:CSRF-Token、SameSite Cookie、校验请求来源
-
CSP策略:资源白名单机制,从根源拦截恶意脚本、XSS注入,是最高级前端安全防御方案
-
URL编码:完整URL用encodeURI,URL参数必须用encodeURIComponent,防止参数解析异常与注入
-
btoa/atob:Base64编解码,仅编码不加密,需兼容中文预处理编码,用于数据脱敏传输
-
SubtleCrypto:浏览器标准安全加密API,支持SHA256/AES/RSA,HTTPS专属,用于真实业务数据加密
八、高频面试简答题
-
DOM型XSS和存储型XSS的区别? 存储型存入服务端、全员触发、危害最大;DOM型纯前端解析、无服务端参与、仅本地触发。
-
CSP为什么能防御XSS? 通过资源白名单拦截内联脚本、eval动态代码、未知第三方脚本,恶意注入代码无法执行,从根源拦截攻击。
-
encodeURI和encodeURIComponent区别? 前者编码完整URL,不解析URL分隔符;后者编码所有特殊字符,专门用于URL参数编码,防止参数篡改。
-
Base64是加密吗? 不是,是编码格式,可直接逆向解码,无安全性,仅用于数据脱敏和传输格式转换。
-
SubtleCrypto为什么比第三方加密库安全? 浏览器原生底层实现、异步安全、算法标准、无源码泄露,仅HTTPS环境可用,杜绝伪造与破解。
-
CSRF的核心防御思路? 打破浏览器自动携带Cookie的信任机制,通过手动Token、Cookie跨站限制区分自愿请求与伪造请求。
-
前端密码如何安全处理? 前端使用SHA256哈希加盐,避免明文传输,禁止Base64简单编码,配合HTTPS传输、后端二次加密校验。