1. 对安全有什么了解?
前端安全不只是"防XSS",而是纵深防御体系(Defense in Depth)。我总结为"三防三控":
- 三防:XSS、CSRF、点击劫持
- 三控:权限控制、输入控制、通信控制
真实业务场景:我们做金融SaaS时,一个富文本编辑器被注入 <script>
,导致用户Token泄露------这就是典型的存储型XSS。
「Q1: XSS有几种类型?分别怎么防御?」
A1: 分3种:
- 存储型:服务端入库前转义(如
<
)或使用DOMPurify库 - 反射型:前端不直接 innerHTML,用 textContent
- DOM型:避免
eval()
、innerHTML
拼接用户输入
👉继续看?💥
「Q2: 为什么转义 < > 就能防XSS?」
A2: 因为 <script>
标签需要尖括号解析,转义后浏览器不会当作标签处理,而是纯文本。
⚠️但这不是万能的!比如在 onerror="alert(1)"
中,引号未闭合仍可执行。
「Q3: 前端能完全防住XSS吗?」
A3: ❌不能!前端是"最后一道防线",核心防御应在服务端。前端做双重校验,提升用户体验。
2. 介绍下数字签名的原理
数字签名 = 非对称加密 + 摘要算法,用来验证数据完整性和身份认证。
流程如下(图示):
⚠️中间人能篡改吗?👉继续看?
核心代码(简化版):
js
// 模拟签名生成(Node.js crypto)
const crypto = require('crypto');
function sign(data, privateKey) {
const hash = crypto.createHash('sha256').update(data).digest(); // 摘要
const signature = crypto.privateEncrypt(privateKey, hash); // 私钥加密
return signature;
}
function verify(data, signature, publicKey) {
const hash = crypto.createHash('sha256').update(data).digest();
const decrypted = crypto.publicDecrypt(publicKey, signature);
return decrypted.equals(hash); // 比对
}
// 注:实际用 sign/verify 方法,此处为原理演示
「Q4: 为什么不用私钥加密全文?」
A4: 因为非对称加密慢且有长度限制。摘要固定长度(如256位),效率高。
「Q5: 中间人篡改数据+重新签名行吗?」
A5: ❌不行!他没有发送方的私钥,无法生成合法签名。接收方用公钥解密失败或摘要不匹配。
3. 前后端通信使用什么方案?
通信方案按场景分:
场景 | 方案 | 说明 |
---|---|---|
普通CRUD | RESTful API | 标准、易调试 |
实时数据 | WebSocket | 如聊天、订单推送 |
文件传输 | FormData + 上传进度 | 配合断点续传 |
微前端 | Custom Event / postMessage | 主子应用通信 |
高性能 | gRPC-Web | 内部系统,ProtoBuf序列化 |
「Q6: REST和gRPC怎么选?」
A6:
- REST:对外API、调试友好、浏览器原生支持
- gRPC:内部服务、性能敏感、多语言场景
👉选错=架构翻车!🤯
4. RESTful常用的Method
Method | 幂等 | 用途 |
---|---|---|
GET | ✅ | 查询 |
POST | ❌ | 创建 |
PUT | ✅ | 全量更新 |
PATCH | ❌ | 部分更新 |
DELETE | ✅ | 删除 |
⚠️面试陷阱:POST一定不幂等?
不一定!如果服务端实现为"创建唯一资源",重复提交应返回409 Conflict,也能做到幂等。
「Q7: 幂等性前端怎么保证?」
A7:
- 前端防抖:按钮点击后禁用
- 唯一请求ID:后端通过
X-Request-ID
去重 - Token机制:提交后Token失效
5. 介绍下跨域
跨域是浏览器的同源策略(Same-Origin Policy)导致的,非服务端限制。
同源 = 协议 + 域名 + 端口 相同。
常见跨域场景:
ascii
前端: http://localhost:3000
后端: http://api.example.com:8080
❌ 协议+域名+端口都不同 → 跨域
解决方案:
- CORS(主流):服务端加响应头
- JSONP:只支持GET,已淘汰
- 代理:开发用webpack proxy,生产用Nginx
- postMessage:iframe通信
「Q8: 为什么说跨域是浏览器行为?」
A8: 因为用curl或Postman发请求,根本不受跨域限制。这是浏览器为保护用户安全设计的。
「Q9: 简单请求和预检请求区别?」
A9:
- 简单请求:GET/POST + text/plain等,直接发
- 预检请求:带自定义头或复杂类型,先发OPTIONS探路
👉预检失败=跨域拦住!
6. Access-Control-Allow-Origin在服务端哪里配置?
在服务端HTTP响应头中设置,位置取决于技术栈:
-
Node.js (Express):
jsapp.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://yourdomain.com'); // 或 * res.header('Access-Control-Allow-Credentials', 'true'); next(); });
-
Nginx:
nginxlocation / { add_header 'Access-Control-Allow-Origin' 'https://yourdomain.com'; add_header 'Access-Control-Allow-Credentials' 'true'; }
-
Java Spring Boot:
@CrossOrigin
注解
⚠️配置 * 时不能带 credentials!否则浏览器拒绝。
「Q10: 如何安全地配置允许多个域名?」
A10: 不能写多个头!需动态判断 origin 是否在白名单,再设置对应值。
👉硬编码=安全漏洞!
7. csrf跨站攻击怎么解决?
CSRF:攻击者诱导用户在已登录状态下发起非自愿请求。
比如:<img src="http://bank.com/transfer?to=evil&amount=1000">
解决方案:
-
SameSite Cookie(推荐):
httpSet-Cookie: session=abc; SameSite=Lax; Secure
- Lax:跨站GET允许,POST拦截
- Strict:完全禁止跨站
-
CSRF Token:
- 服务端生成 token,前端表单提交时带上
- 服务端校验 token 是否匹配
-
双重提交 Cookie:
- 前端从 cookie 读 token,放入 header 提交
- 服务端比对 cookie 和 header 中的 token
「Q11: 为什么加 token 就能防CSRF?」
A11: 因为攻击者无法读取 cookie(同源策略),拿不到 token,请求被拒绝。
「Q12: SameSite=Lax 和 Strict 区别?」
A12:
- Lax:允许导航式GET(如点击链接)
- Strict:任何跨站都不行,体验差
👉电商常用 Lax
8. 前端和后端怎么联调?
联调流程的"三阶联调法":
- 契约先行:用 Swagger/OpenAPI 定义接口,前端 mock 数据开发
- 本地代理:webpack proxy 指向测试环境
- 联调环境:共用测试服,用 Charles/Fiddler 抓包
工具链:
- 接口文档:Swagger / YAPI
- Mock:MSW(Mock Service Worker)
- 调试:Chrome DevTools + 日志追踪ID
「Q13: 接口字段不一致怎么处理?」
A13:
- 用 TypeScript 接口同步定义
- 自动化生成 DTO,避免手写错误
👉手动维护=bug温床!
「Q14: 如何快速定位是前端还是后端问题?」
A14:
- 看请求:数据发出去了吗?格式对吗?
- 看响应:状态码?数据结构?
- 看日志:前后端加 traceId 串联