前端秋招复习:XSS、CSRF 与常见 Web 安全问题

0 阅读15分钟

前端秋招复习:XSS、CSRF 与常见 Web 安全问题

前言

前端安全面试中,最常见的两个问题是:

什么是 XSS?
什么是 CSRF?

很多同学背得出全称,却说不清攻击过程,也容易把 HttpOnlySameSite、CORS、CSP 等防护手段混在一起。

这篇文章面向前端秋招复盘,不深入攻击绕过和服务端安全框架,重点是理解:

攻击为什么能够发生;
前端代码哪里容易出问题;
常见防护手段分别解决什么问题;
面试时怎样用几句话回答清楚。

先记住核心区别:

XSS 是让不可信内容在页面中作为代码执行;CSRF 是借用用户已经登录的身份发送非本人意愿的请求。


一、先看 XSS 和 CSRF 的区别

对比项XSSCSRF
中文跨站脚本攻击跨站请求伪造
核心问题不可信内容被当成代码执行用户身份被借用发送请求
是否依赖用户登录不一定通常依赖已有登录态
攻击者是否需要知道 Cookie不一定通常不需要知道,只利用浏览器自动携带
主要防护转义、净化、安全 DOM API、CSPCSRF Token、SameSite、来源校验

可以简单记成:

XSS  → 注入并执行代码
CSRF → 伪造用户请求

二、XSS 是什么

XSS 全称是:

Cross-Site Scripting
跨站脚本攻击

它的核心是:

网站把不可信数据放进了危险位置,浏览器将其当成 HTML 或 JavaScript 执行。

假设评论区原本只想显示用户输入的文本:

这篇文章写得很好

如果页面直接把评论作为 HTML 插入,攻击者可能提交带有事件代码的内容:

<img src="invalid" onerror="alert('XSS')">

浏览器解析这段 HTML 后,就可能执行其中的代码。

攻击流程可以简化为:

攻击者提供恶意内容
        ↓
网站没有正确转义或净化
        ↓
内容进入 innerHTML 等危险位置
        ↓
浏览器将内容当成代码执行

XSS 可能造成什么影响

恶意脚本运行在目标网站页面中,因此可能:

  • 读取页面中的敏感信息;
  • 修改页面内容;
  • 冒充用户调用接口;
  • 读取 JavaScript 可以访问的本地数据;
  • 诱导用户输入账号或密码。

三、XSS 有哪些常见类型

秋招面试通常掌握三种即可。

1. 存储型 XSS

恶意内容被保存到数据库,其他用户访问页面时又被读取并执行。

攻击者提交恶意评论
        ↓
服务器保存到数据库
        ↓
其他用户查看评论
        ↓
浏览器执行恶意内容

常见场景:

评论、论坛帖子、用户昵称、个人简介、后台工单

它的特点是影响可能比较持久,并且可能波及多个用户。

2. 反射型 XSS

恶意内容没有长期保存,而是通过本次请求进入服务器响应。

例如服务器把搜索参数直接拼进 HTML:

用户点击特殊链接
        ↓
参数被发送给服务器
        ↓
服务器把参数直接返回到页面
        ↓
浏览器执行危险内容

它通常依赖攻击者诱导用户点击特制链接。

3. DOM 型 XSS

DOM 型 XSS 主要发生在浏览器端。

例如前端读取 URL 参数后直接写入 innerHTML

const keyword = new URLSearchParams(location.search).get('keyword')

document.querySelector('.result').innerHTML = keyword

更安全的文本展示方式是:

document.querySelector('.result').textContent = keyword

三种类型对比:

类型恶意内容主要来自哪里是否通常保存到数据库常见场景
存储型数据库等持久化数据评论、帖子、用户资料
反射型当前请求参数搜索页、错误页、特殊链接
DOM 型URL、DOM 等前端数据不一定innerHTMLdocument.write

三者虽然来源不同,但最终问题相同:

不可信数据进入了危险的执行位置。

四、Vue 项目中为什么仍然可能有 XSS

Vue 的普通插值会把数据作为文本处理:

<p>{{ comment }}</p>

假设 comment 是:

<strong>你好</strong>

普通插值通常会显示标签文本,而不是把它作为真正的 HTML 标签渲染。

但是下面的写法需要特别小心:

<div v-html="comment"></div>

v-html 会把字符串作为 HTML 插入页面。如果内容来自用户输入,就可能产生风险。

同样需要谨慎使用:

element.innerHTML = userInput
element.outerHTML = userInput
document.write(userInput)

所以不能认为“使用 Vue 就绝对不会出现 XSS”。框架提供了默认保护,但开发者仍可能通过 v-html 或手动 DOM 操作绕开保护。


五、怎样防御 XSS

1. 把不可信数据作为文本

原生 DOM 操作优先使用:

element.textContent = userInput

而不是直接使用:

element.innerHTML = userInput

Vue 中普通文本优先使用:

<p>{{ userInput }}</p>

核心思想是:

用户输入应该被当成数据,而不是代码。

2. 根据输出位置进行转义

例如将 HTML 中具有特殊含义的字符转换成实体:

<  →  &lt;
>  →  &gt;

这样浏览器会显示标签文本,而不会把它解析成真正的标签。

HTML、属性、URL、JavaScript 的解析规则不同,因此应该根据数据最终进入的位置进行安全处理,不能只靠一条简单正则替换所有危险内容。

3. 富文本先净化再渲染

文章编辑器等业务需要保留 <p><strong> 等标签,不能把所有 HTML 都转义。

这时应使用经过维护的 HTML Sanitizer,按照允许列表移除危险标签、属性和协议:

const safeHTML = sanitize(untrustedHTML)

element.innerHTML = safeHTML

不要尝试自己用一条正则完整过滤 HTML。

4. 给敏感 Cookie 设置 HttpOnly

服务端可以设置:

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax

HttpOnly 会阻止 JavaScript 通过 document.cookie 读取该 Cookie,可以降低会话 Cookie 被直接窃取的风险。

但它不能阻止 XSS 代码执行,恶意脚本仍可能修改页面或者以当前用户身份调用接口。

5. 使用 CSP 作为额外防线

CSP 全称是内容安全策略,服务器可以通过响应头限制页面允许加载和执行的资源来源:

Content-Security-Policy: default-src 'self'; script-src 'self'

CSP 可以降低部分恶意脚本执行和外部资源加载风险,但它属于纵深防御,不能代替转义和 HTML 净化。

6. 避免执行不可信字符串

谨慎使用:

eval(userInput)
new Function(userInput)
setTimeout(userInput, 1000)

如果字符串来自不可信来源,就可能被当成 JavaScript 执行。


六、CSRF 是什么

CSRF 全称是:

Cross-Site Request Forgery
跨站请求伪造

它的核心是:

攻击者诱导已经登录目标网站的用户,从其他网站向目标网站发送一个非本人意愿的请求。

假设用户已经登录银行网站,浏览器保存了登录 Cookie:

Cookie: sessionId=abc123

用户随后打开了攻击网站,攻击网站构造了一个指向银行接口的表单:

<form action="https://bank.example/api/change-email" method="post">
  <input type="hidden" name="email" value="other@example.com">
</form>

在满足 Cookie 发送规则的情况下,浏览器可能自动携带银行网站的登录 Cookie。服务器如果只检查 Cookie,就可能误以为这是用户主动操作。

完整流程是:

用户登录目标网站
        ↓
浏览器保存登录 Cookie
        ↓
用户访问攻击网站
        ↓
攻击网站诱导浏览器向目标网站发送请求
        ↓
浏览器可能自动带上目标网站的 Cookie
        ↓
服务器误以为这是用户主动操作

攻击者通常不需要知道 Cookie 的具体值,它利用的是浏览器自动携带 Cookie 的机制。

CSRF 通常需要哪些条件

可以简单记住三个条件:

用户已经登录目标网站;
浏览器会自动携带身份凭证;
目标接口没有验证请求是否来自用户真实意愿。

七、同源策略为什么没有自动阻止 CSRF

同源策略主要限制攻击页面读取其他源的数据,但不代表所有跨站请求都无法发送。

浏览器允许一些跨站行为,例如:

<img src="https://other.example/image.png">

<form action="https://other.example/api/action" method="post">

所以可以简单理解为:

发送某些跨站请求:可能允许
读取跨站响应内容:通常受到同源策略或 CORS 限制

CSRF 通常只需要让修改操作成功,并不一定需要读取响应。例如修改邮箱、提交订单或者关注用户。

因此:

攻击网站看不到响应,不代表伪造请求没有产生影响。


八、怎样防御 CSRF

1. 使用 CSRF Token

服务器为正常用户会话生成一个攻击者难以获得的随机 Token:

正常页面获得 CSRF Token
        ↓
提交敏感请求时携带 Token
        ↓
服务器同时校验登录态和 Token

例如:

POST /api/change-email HTTP/1.1
X-CSRF-Token: random-value

攻击网站可能诱导浏览器自动携带 Cookie,但通常无法读取正常网站页面中的 Token,也不能通过普通跨站表单设置这个自定义请求头。

2. 设置 SameSite Cookie

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax

三个常见取值可以简单理解为:

基础理解
Strict跨站场景限制最严格,但可能影响正常跳转体验
Lax允许部分顶层安全导航,限制许多跨站请求携带 Cookie
None允许跨站携带,通常必须同时设置 Secure

SameSite 是重要防线,但复杂业务中通常还需要结合其他措施。

3. 校验请求来源

服务端可以检查 Origin 等请求头,确认修改状态的请求来自允许的站点:

Origin: https://app.example.com

4. 敏感操作再次验证

转账、修改密码等高风险操作可以要求:

重新输入密码;
短信或邮箱验证码;
多因素认证;
二次确认。

5. 不要使用 GET 修改数据

下面的接口设计不合理:

GET /api/delete-user?id=1001

GET 应主要用于获取资源,不应该执行删除、转账等修改状态的操作。

但要注意:

只把 GET 改成 POST 也不能彻底防止 CSRF,因为攻击者可以通过 HTML 表单构造部分 POST 请求。


九、Cookie 三个安全属性分别有什么用

Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Lax
属性作用主要关联风险
HttpOnly禁止 JavaScript 读取 Cookie降低 XSS 窃取 Cookie 的风险
Secure只通过 HTTPS 发送 Cookie降低不安全传输风险
SameSite限制部分跨站请求携带 Cookie降低 CSRF 风险

注意它们都不是万能开关:

HttpOnly 不能阻止 XSS 代码执行;
Secure 不能单独防止 XSS 或 CSRF;
SameSite 也不应该成为唯一的 CSRF 防线。

十、使用 Authorization Token 就没有 CSRF 了吗

假设前端手动把 Token 放进请求头:

fetch('/api/user', {
  headers: {
    Authorization: `Bearer ${token}`
  }
})

攻击网站通常不能让浏览器自动为目标网站添加这个 Authorization 请求头,所以它一般不容易受到传统 Cookie 型 CSRF。

但这不等于 Token 一定安全:

Token 放在 localStorage 中 → XSS 脚本可能读取
Token 放在自动发送的 Cookie 中 → 仍要考虑 CSRF

因此不能简单背成“Cookie 不安全,Token 安全”。不同存放和发送方式面对的风险不同。


十一、几个容易混淆的问题

1. CORS 能防止 CSRF 吗

不能直接画等号。

CORS 主要决定某个源的 JavaScript 是否可以跨源读取响应,以及能否发送某些跨源请求;CSRF 则可能利用表单等浏览器已有能力发送请求,而且不需要读取响应。

所以防御 CSRF 仍应依靠:

CSRF Token、SameSite、Origin 校验等措施。

2. HTTPS 能防止 XSS 和 CSRF 吗

不能。

HTTPS 主要保护浏览器和服务器之间的传输,降低数据被窃听和篡改的风险。

XSS 和 CSRF 属于应用逻辑问题,即使网站使用 HTTPS,也仍然可能存在。不过 HTTPS 是其他安全措施可靠工作的基础。

3. 什么是点击劫持

攻击者把目标网站放进透明或伪装的 iframe,诱导用户点击看似正常的按钮,实际点击了目标网站中的敏感操作。

常见防护响应头:

Content-Security-Policy: frame-ancestors 'self'

也可以使用兼容方案:

X-Frame-Options: SAMEORIGIN

4. 前端路由守卫能代替后端鉴权吗

不能。

路由守卫只能控制页面跳转和界面显示,用户仍然可以绕过页面直接发送请求。服务器必须重新验证身份、权限和数据归属。

前端权限控制 → 改善界面和交互体验
后端权限校验 → 决定操作是否真正允许

5. 前端环境变量能保存秘密吗

前端代码最终会下载到用户浏览器,因此构建进前端产物的变量可以被用户查看。

数据库密码、服务端私钥和高权限密钥不能因为写进 .env 就认为安全。

6. 前端输入校验能阻止攻击吗

前端校验可以改善用户体验,但攻击者能够绕开页面直接构造请求,所以服务端仍需校验参数、权限和业务规则。


十二、XSS 和 CSRF 有什么关系

如果网站已经存在 XSS,恶意脚本会运行在目标网站自己的页面中,因此可能:

读取页面中的 CSRF Token;
直接调用同源接口;
模拟用户完成操作。

所以严重的 XSS 往往能够绕过很多 CSRF 防护。

这也是为什么不能只处理 CSRF,而忽略页面中的 XSS 漏洞。


十三、常见面试追问

1. innerHTML 一定不能用吗

不是完全不能用,而是不能直接插入不可信内容。普通文本优先使用 textContent,必须渲染富文本时先使用可靠方案进行 HTML 净化。

2. Vue 的插值能防 XSS 吗

Vue 普通插值会转义文本,能够降低常见 HTML 注入风险。但 v-html、不安全 URL、第三方组件和手动 DOM 操作仍可能带来风险。

3. HttpOnly 能彻底防止 XSS 吗

不能。它只阻止 JavaScript 读取该 Cookie,不能阻止恶意脚本执行、修改页面或调用接口。

4. SameSite 能彻底防止 CSRF 吗

不能简单这样说。SameSite 能限制很多跨站请求携带 Cookie,但实际项目通常还会结合 CSRF Token、来源校验和敏感操作二次验证。

5. 只允许 POST 能防 CSRF 吗

不能。攻击者可以使用 HTML 表单构造部分 POST 请求。

6. XSS 能绕过 CSRF Token 吗

有可能。因为 XSS 代码运行在目标网站页面中,可能读取页面里的 Token,或者直接调用同源接口。

7. Token 应该放 localStorage 还是 Cookie

没有脱离场景的绝对答案:

localStorage 中的 Token → 不会自动随请求发送,但可能被 XSS 读取
HttpOnly Cookie → JavaScript 不能读取,但要考虑自动携带带来的 CSRF

项目需要结合 XSS 防护、SameSite、CSRF Token、跨域和登录刷新机制统一设计。

8. SQL 注入应该怎样防

SQL 注入主要由服务端使用参数化查询、预编译语句或正确使用 ORM 进行防护。前端校验容易被绕过,不能作为安全边界。


十四、面试回答模板

XSS

XSS 是跨站脚本攻击,本质是不可信数据进入了页面的危险位置,被浏览器当成代码执行。常见类型有存储型、反射型和 DOM 型。防护上应使用框架默认转义和 textContent 等安全 API,避免直接插入不可信 HTML;必须渲染富文本时进行净化,并使用 CSP、HttpOnly 等措施降低风险。

CSRF

CSRF 是跨站请求伪造。用户登录目标网站后,攻击者诱导用户从其他网站发送请求,浏览器可能自动携带登录 Cookie,服务器如果没有验证请求意图,就可能执行敏感操作。常见防护包括 CSRF Token、SameSite Cookie、来源校验和敏感操作二次验证。

二者区别

XSS 关注恶意代码在可信页面中执行,CSRF 关注借用用户已有身份发送伪造请求。XSS 主要通过转义、净化和安全 DOM API 防护;CSRF 主要通过 Token、SameSite 和来源校验防护。


十五、秋招复习重点

必须掌握

XSS 和 CSRF 的核心原理;
存储型、反射型和 DOM 型 XSS;
XSS 与 CSRF 的区别;
二者的主要防护方式;
HttpOnly、Secure、SameSite 的作用。

常见追问

为什么 innerHTML、v-html 有风险;
为什么只允许 POST 不能防 CSRF;
CORS 为什么不等于 CSRF 防护;
HTTPS 为什么不能直接防 XSS、CSRF;
Token 放 Cookie 和 localStorage 的安全侧重点;
前端路由守卫为什么不能代替后端鉴权。

最后记住:

XSS 重点防止“不可信数据变成代码”,CSRF 重点防止“登录凭证被用于伪造请求”。前端负责安全渲染,服务端负责身份、权限和请求真实性校验。


参考资料