前端安全相关面试题(20题)
1. 什么是XSS攻击?有哪些类型?如何防范?
参考答案:
XSS(Cross-Site Scripting)跨站脚本攻击是指攻击者在网页中注入恶意脚本代码,当用户浏览该网页时,脚本会在用户浏览器中执行。
类型:
存储型XSS:恶意脚本被存储在服务器数据库中
反射型XSS:恶意脚本通过URL参数等方式反射给用户
DOM型XSS:通过修改DOM结构来执行恶意脚本
防范措施:
输入验证和输出编码
使用CSP(Content Security Policy)
设置HttpOnly Cookie
使用安全的DOM操作方法
2. 什么是CSRF攻击?如何防范?
参考答案:
CSRF(Cross-Site Request Forgery)跨站请求伪造是指攻击者诱导用户在已登录的网站上执行非本意的操作。
防范措施:
使用CSRF Token验证
检查Referer头
使用SameSite Cookie属性
重要操作添加验证码
使用双重Cookie验证
3. 什么是CSP?如何配置和使用?
参考答案:
CSP(Content Security Policy)内容安全策略是一种安全机制,用于检测和减轻XSS攻击。
配置方式:
<!-- HTTP头配置 -->
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
<!-- Meta标签配置 -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">常用指令:
default-src:默认策略script-src:脚本来源style-src:样式来源img-src:图片来源
4. 什么是点击劫持攻击?如何防范?
参考答案:
点击劫持(Clickjacking)是指攻击者使用透明或不可见的iframe覆盖在正常网页上,诱导用户点击。
防范措施:
设置X-Frame-Options头:
DENY、SAMEORIGIN使用CSP的frame-ancestors指令
JavaScript框架检测:
if (top !== window) {
top.location = window.location;
}5. Cookie有哪些安全属性?分别有什么作用?
参考答案:
安全属性:
HttpOnly:防止JavaScript访问Cookie,减少XSS攻击
Secure:只在HTTPS连接中传输Cookie
SameSite:控制跨站请求时是否发送Cookie
Strict:完全禁止跨站发送Lax:部分跨站请求可发送None:允许跨站发送(需配合Secure)
document.cookie = "sessionId=abc123; HttpOnly; Secure; SameSite=Strict";6. 什么是SQL注入?前端如何防范?
参考答案:
SQL注入是指攻击者通过在输入中插入恶意SQL代码来操作数据库。
前端防范:
输入验证和过滤
使用参数化查询(后端配合)
对特殊字符进行转义
限制输入长度和格式
使用白名单验证
// 输入验证示例
function validateInput(input) {
const sqlKeywords = /(\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION)\b)/i;
return !sqlKeywords.test(input);
}7. 什么是同源策略?如何安全地进行跨域请求?
参考答案:
同源策略要求协议、域名、端口完全相同才能访问资源。
安全跨域方案:
CORS:服务器设置Access-Control-Allow-Origin
JSONP:仅支持GET请求,存在安全风险
代理服务器:后端代理请求
PostMessage:用于iframe通信
// CORS示例
fetch('https://api.example.com/data', {
method: 'POST',
credentials: 'include', // 发送Cookie
headers: {
'Content-Type': 'application/json'
}
});8. 如何安全地存储敏感信息?
参考答案:
存储方案对比:
LocalStorage/SessionStorage:明文存储,XSS可访问
Cookie:可设置HttpOnly,但仍有CSRF风险
IndexedDB:XSS可访问
安全措施:
敏感信息加密存储
使用短期Token代替长期凭证
定期清理存储数据
避免在前端存储密码等敏感信息
// 加密存储示例
const encryptData = (data, key) => {
return CryptoJS.AES.encrypt(JSON.stringify(data), key).toString();
};9. 什么是中间人攻击?如何防范?
参考答案:
中间人攻击(MITM)是指攻击者在通信双方之间拦截和修改数据。
防范措施:
使用HTTPS加密传输
验证SSL证书
使用HSTS(HTTP Strict Transport Security)
证书固定(Certificate Pinning)
避免使用公共WiFi进行敏感操作
// HSTS头设置
Strict-Transport-Security: max-age=31536000; includeSubDomains10. 如何防范恶意文件上传?
参考答案:
前端防范:
文件类型验证(MIME类型检查)
文件大小限制
文件名过滤
文件内容检测
function validateFile(file) {
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
const maxSize = 5 * 1024 * 1024; // 5MB
if (!allowedTypes.includes(file.type)) {
throw new Error('不支持的文件类型');
}
if (file.size > maxSize) {
throw new Error('文件过大');
}
return true;
}11. 什么是DOM Clobbering攻击?如何防范?
参考答案:
DOM Clobbering是指通过HTML注入来覆盖全局变量或DOM属性,影响JavaScript代码执行。
攻击示例:
<img name="userConfig" src="x">
<script>
// 原本期望的对象被覆盖
console.log(window.userConfig); // 输出img元素而非配置对象
</script>防范措施:
避免使用全局变量
使用命名空间
严格的HTML过滤
使用
hasOwnProperty检查属性
12. 什么是原型污染攻击?如何防范?
参考答案:
原型污染是指攻击者修改JavaScript对象的原型,影响所有实例对象。
攻击示例:
// 恶意输入
const maliciousInput = '{"__proto__": {"isAdmin": true}}';
const userData = JSON.parse(maliciousInput);
// 所有对象都被污染
console.log({}.isAdmin); // true防范措施:
使用
Object.create(null)创建纯净对象使用
Map代替普通对象输入验证,过滤
__proto__等危险属性使用
Object.freeze()冻结原型
13. 如何安全地处理用户输入?
参考答案:
处理原则:
永远不信任用户输入
输入验证:白名单验证优于黑名单
输出编码:根据上下文选择编码方式
长度限制:防止DoS攻击
// 输入清理函数
function sanitizeInput(input) {
return input
.replace(/[<>\"']/g, '') // 移除危险字符
.trim()
.substring(0, 1000); // 长度限制
}
// HTML编码
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}14. 什么是依赖混淆攻击?如何防范?
参考答案:
依赖混淆攻击是指攻击者上传恶意包到公共仓库,利用包管理器的解析机制让应用下载恶意包。
防范措施:
使用私有npm仓库
锁定依赖版本(package-lock.json)
定期审计依赖包:
npm audit使用
.npmrc配置可信源监控依赖包的异常行为
// .npmrc配置示例
@company:registry=https://private-registry.company.com/
registry=https://registry.npmjs.org/15. 如何防范ReDoS(正则表达式拒绝服务)攻击?
参考答案:
ReDoS攻击利用正则表达式的回溯特性,通过特殊输入导致CPU占用过高。
危险模式:
// 危险的正则表达式
const badRegex = /^(a+)+$/;
const input = 'a'.repeat(25) + 'X'; // 触发灾难性回溯防范措施:
避免嵌套量词:
(a+)+、(a*)*使用具体量词:
{1,10}代替+设置超时限制
使用正则表达式安全检测工具
考虑使用有限状态自动机
16. 什么是Tabnabbing攻击?如何防范?
参考答案:
Tabnabbing攻击是指恶意网站通过window.opener修改原页面,进行钓鱼攻击。
攻击场景:
// 恶意页面代码
if (window.opener) {
window.opener.location = 'https://fake-bank.com/login';
}防范措施:
// 使用rel="noopener noreferrer"
<a href="https://external-site.com" target="_blank" rel="noopener noreferrer">链接</a>
// JavaScript打开窗口时清除opener
const newWindow = window.open('https://external-site.com');
newWindow.opener = null;17. 如何安全地使用eval()和Function构造函数?
参考答案:
安全原则:
避免使用:优先使用JSON.parse()、模板字符串等替代方案
输入验证:严格验证和过滤输入
沙箱环境:在受限环境中执行
// 危险用法
eval(userInput); // 永远不要这样做
// 安全替代方案
// 1. JSON解析
const data = JSON.parse(jsonString);
// 2. 模板字符串
const template = `Hello ${name}`;
// 3. 使用安全的解析库
const safeEval = require('safe-eval');
safeEval(code, context);18. 什么是子资源完整性(SRI)?如何使用?
参考答案:
SRI(Subresource Integrity)用于验证外部资源的完整性,防止CDN劫持等攻击。
使用方法:
<!-- 为外部脚本添加integrity属性 -->
<script src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>
<link rel="stylesheet"
href="https://cdn.example.com/style.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">生成哈希值:
# 使用openssl生成SHA384哈希
openssl dgst -sha384 -binary file.js | openssl base64 -A19. 如何防范WebSocket安全风险?
参考答案:
主要风险:
跨站WebSocket劫持
缺乏同源策略保护
数据传输安全
防范措施:
// 1. 使用WSS加密连接
const socket = new WebSocket('wss://secure-server.com/socket');
// 2. 验证Origin头(服务端)
if (request.headers.origin !== 'https://trusted-domain.com') {
return reject();
}
// 3. 使用Token认证
socket.onopen = function() {
socket.send(JSON.stringify({
type: 'auth',
token: getAuthToken()
}));
};
// 4. 输入验证
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
if (validateMessage(data)) {
processMessage(data);
}
};20. 如何实现安全的前端日志记录?
参考答案:
安全考虑:
避免记录敏感信息
防止日志注入攻击
控制日志级别
class SecurityLogger {
constructor() {
this.sensitiveFields = ['password', 'token', 'ssn', 'creditCard'];
}
// 清理敏感信息
sanitizeData(data) {
const cleaned = { ...data };
this.sensitiveFields.forEach(field => {
if (cleaned[field]) {
cleaned[field] = '***';
}
});
return cleaned;
}
// 防止日志注入
escapeLogData(message) {
return message.replace(/[\r\n]/g, '');
}
log(level, message, data = {}) {
const cleanData = this.sanitizeData(data);
const safeMessage = this.escapeLogData(message);
console.log(`[${level}] ${safeMessage}`, cleanData);
// 发送到安全的日志服务
this.sendToLogService(level, safeMessage, cleanData);
}
}这些面试题涵盖了前端安全的核心知识点,包括常见攻击手段、防范措施、安全最佳实践等。在实际面试中,面试官可能会深入询问具体的实现细节或结合实际项目场景进行讨论。