随着互联网的快速发展,Web应用安全问题日益突出。作为前端开发者,了解常见的安全威胁及其防御措施至关重要。本文将重点介绍两种最常见的前端安全威胁:跨站脚本攻击(XSS)和跨站请求伪造(CSRF),并提供实用的防御策略。
XSS(Cross-Site Scripting,跨站脚本)攻击是一种注入类型的攻击,攻击者通过在目标网站上注入恶意脚本代码,当用户浏览该页面时,恶意代码会在用户的浏览器上执行,从而窃取用户数据、会话令牌或重定向用户到其他网站。
// 存储型XSS示例 - 恶意用户在评论中提交
const userComment = "";
// 反射型XSS示例 - URL参数注入
// https://example.com/search?q=
// DOM型XSS示例
document.getElementById("demo").innerHTML = location.hash.substring(1);
// 当URL为 https://example.com#
时触发
始终验证并过滤用户输入,拒绝包含可疑脚本的内容。
// 使用DOMPurify库过滤用户输入
import DOMPurify from 'dompurify';
const userInput = "";
const sanitizedInput = DOMPurify.sanitize(userInput);
// 输出: ""
在将数据输出到HTML、JavaScript、CSS或URL时,对数据进行适当的编码。
// HTML编码
function htmlEncode(str) {
return String(str)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
const userContent = "";
const safeContent = htmlEncode(userContent);
// 输出: "<script>alert('XSS')</script>"
内容安全策略通过限制资源的加载来防止XSS攻击。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted-cdn.com">
或在服务器响应中设置HTTP头:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com
现代JavaScript框架(如React、Vue、Angular)自带XSS防御机制,默认情况下会转义HTML内容。
// React自动转义用户输入
function Comment({ text }) {
return {text}; // React自动进行HTML转义
}
通过设置Cookie的HttpOnly标志,使JavaScript无法访问关键Cookie。
Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种攻击方式,攻击者诱导已登录用户访问包含恶意请求的网站,利用用户的身份在用户不知情的情况下执行未授权的操作。
假设用户已登录银行网站,银行转账API为:
POST /api/transfer
Content-Type: application/x-www-form-urlencoded
amount=1000&to=account123
攻击者可以创建以下页面诱导用户点击:
<html>
<body>
<h1>赢取免费奖品!h1>
<form action="https://bank.example/api/transfer" method="POST" id="csrf-form">
<input type="hidden" name="amount" value="10000">
<input type="hidden" name="to" value="attacker-account">
form>
<script>
document.getElementById("csrf-form").submit();
script>
body>
html>
在表单中添加一个随机生成的令牌,服务器验证该令牌的有效性。
<form action="/api/transfer" method="post">
<input type="hidden" name="csrf_token" value="随机生成的令牌">
<input type="text" name="amount">
<input type="text" name="to">
<button type="submit">转账button>
form>
服务器端验证:
// 伪代码
if (request.csrfToken !== session.csrfToken) {
return response.status(403).send('CSRF验证失败');
}
验证请求头中的Origin或Referer字段,确保请求来自可信来源。
// 服务器端伪代码
const origin = request.headers.origin || request.headers.referer;
if (!isAllowedOrigin(origin)) {
return response.status(403).send('禁止跨站请求');
}
设置Cookie的SameSite属性可以防止跨站请求发送Cookie。
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly
SameSite有三个值:
Strict
:完全禁止第三方网站发送CookieLax
:允许部分跨站请求(如链接导航)发送CookieNone
:允许所有跨站请求发送Cookie(需要同时设置Secure属性)对于AJAX请求,添加自定义请求头,利用CORS机制阻止跨站请求。
// 前端AJAX请求
fetch('/api/transfer', {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json'
},
body: JSON.stringify({ amount: 1000, to: 'account123' })
});
服务器验证请求头:
// 服务器端伪代码
if (request.headers['x-requested-with'] !== 'XMLHttpRequest') {
return response.status(403).send('非法请求');
}
在客户端和服务器之间使用双重提交Cookie进行验证。
// 客户端JavaScript
// 将CSRF token同时保存在Cookie和表单中
document.cookie = "csrfToken=随机令牌; SameSite=Strict; Secure";
document.getElementById("csrfField").value = "随机令牌";
服务器端验证:
// 服务器端伪代码
if (request.cookies.csrfToken !== request.body.csrfToken) {
return response.status(403).send('CSRF验证失败');
}
XSS和CSRF是前端开发面临的两大主要安全威胁,但通过实施适当的防御措施,可以有效降低这些风险。作为开发人员,我们有责任编写安全的代码,保护用户数据和系统安全。安全不是一次性工作,而是需要持续关注和改进的过程。