安全机制
同源策略
基本概念
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
同源判断
javascript
// 同源
https://example.com/page1.html
https://example.com/page2.html
// 不同源
https://example.com/page1.html
https://other.com/page2.html
// 不同源(协议不同)
https://example.com/page1.html
http://example.com/page2.html
// 不同源(端口不同)
https://example.com:8080/page1.html
https://example.com:8081/page2.html同源策略限制
javascript
// 限制1: 无法读取不同源的Cookie、LocalStorage、SessionStorage
// 限制2: 无法访问不同源的DOM
// 限制3: 无法发送AJAX请求到不同源(除非使用CORS)跨域资源共享(CORS)
基本概念
CORS是一种机制,允许服务器声明哪些源可以访问资源。
简单请求
javascript
// 简单请求: GET、POST、HEAD
// Content-Type: text/plain、multipart/form-data、application/x-www-form-urlencoded
fetch('https://api.example.com/data', {
method: 'GET',
mode: 'cors'
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));预检请求
javascript
// 预检请求: PUT、DELETE、PATCH
// Content-Type: application/json
fetch('https://api.example.com/data', {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));服务器设置
javascript
// Express.js
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});携带凭证
javascript
fetch('https://api.example.com/data', {
method: 'GET',
mode: 'cors',
credentials: 'include'
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));内容安全策略(CSP)
基本概念
CSP是一种安全机制,防止XSS攻击,限制资源加载来源。
设置CSP
html
<!-- 使用meta标签 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com">
<!-- 使用HTTP头 -->
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.comCSP指令
http
default-src 'self'
script-src 'self' 'unsafe-inline' https://cdn.example.com
style-src 'self' 'unsafe-inline'
img-src 'self' data: https:
font-src 'self' https://fonts.googleapis.com
connect-src 'self' https://api.example.com
media-src 'self' https://media.example.com
object-src 'none'
frame-src 'self' https://embed.example.com
base-uri 'self'
form-action 'self'
frame-ancestors 'none'
report-uri /csp-reportCSP示例
html
<!-- 严格策略 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
<!-- 允许CDN -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' https://cdn.example.com">
<!-- 允许内联脚本 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'">
<!-- 报告违规 -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; report-uri /csp-report">XSS攻击
基本概念
XSS(Cross-Site Scripting)跨站脚本攻击,攻击者在网页中注入恶意脚本。
XSS类型
1. 反射型XSS
html
<!-- 不安全的代码 -->
<div>
用户输入: <?php echo $_GET['input']; ?>
</div>
<!-- 攻击示例 -->
<!-- ?input=<script>alert('XSS')</script> -->2. 存储型XSS
html
<!-- 不安全的代码 -->
<div>
评论: <?php echo $comment; ?>
</div>
<!-- 攻击示例 -->
<!-- 评论内容: <script>alert('XSS')</script> -->3. DOM型XSS
javascript
// 不安全的代码
const userInput = document.getElementById('input').value;
document.getElementById('output').innerHTML = userInput;
// 攻击示例
// 输入: <img src=x onerror=alert('XSS')>XSS防护
1. 输入验证
javascript
// 验证输入
function validateInput(input) {
const allowedChars = /^[a-zA-Z0-9 ]+$/;
return allowedChars.test(input);
}
const userInput = document.getElementById('input').value;
if (validateInput(userInput)) {
document.getElementById('output').textContent = userInput;
}2. 输出编码
javascript
// HTML编码
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
const userInput = document.getElementById('input').value;
document.getElementById('output').innerHTML = escapeHtml(userInput);3. 使用textContent
javascript
// 使用textContent代替innerHTML
const userInput = document.getElementById('input').value;
document.getElementById('output').textContent = userInput;4. 使用CSP
html
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'">CSRF攻击
基本概念
CSRF(Cross-Site Request Forgery)跨站请求伪造,攻击者诱使用户在已认证的网站上执行非预期操作。
CSRF攻击示例
html
<!-- 攻击者网站 -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">CSRF防护
1. 使用CSRF Token
javascript
// 生成CSRF Token
function generateCsrfToken() {
return Math.random().toString(36).substring(2);
}
// 存储Token
const csrfToken = generateCsrfToken();
document.cookie = `csrf_token=${csrfToken}; path=/`;
// 发送请求时携带Token
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
},
body: JSON.stringify({ name: 'John' })
});2. 验证Referer
javascript
// 验证Referer
app.use((req, res, next) => {
const referer = req.headers.referer;
if (referer && referer.startsWith('https://example.com')) {
next();
} else {
res.status(403).send('Forbidden');
}
});3. 使用SameSite Cookie
javascript
// 设置SameSite属性
document.cookie = 'session_id=abc123; SameSite=Strict';
document.cookie = 'session_id=abc123; SameSite=Lax';
document.cookie = 'session_id=abc123; SameSite=None; Secure';点击劫持
基本概念
点击劫持是一种攻击方式,攻击者通过透明的iframe覆盖目标网站,诱使用户点击。
点击劫持示例
html
<!-- 攻击者网站 -->
<iframe src="https://bank.com" style="opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe>
<button style="position: absolute; top: 100px; left: 100px;">点击领取奖品</button>点击劫持防护
1. 使用X-Frame-Options
http
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM https://example.com2. 使用CSP
html
<meta http-equiv="Content-Security-Policy"
content="frame-ancestors 'none'">3. 使用JavaScript
javascript
// 检测是否在iframe中
if (window.self !== window.top) {
window.top.location = window.self.location;
}Cookie安全
Cookie属性
javascript
// 设置Cookie
document.cookie = 'name=value; expires=Wed, 21 Oct 2024 07:28:00 GMT; path=/; domain=example.com; secure; HttpOnly; SameSite=Strict';Cookie安全属性
1. Secure
javascript
// 只在HTTPS连接中发送Cookie
document.cookie = 'session_id=abc123; secure';2. HttpOnly
javascript
// 防止JavaScript访问Cookie
document.cookie = 'session_id=abc123; HttpOnly';3. SameSite
javascript
// 防止CSRF攻击
document.cookie = 'session_id=abc123; SameSite=Strict';
document.cookie = 'session_id=abc123; SameSite=Lax';
document.cookie = 'session_id=abc123; SameSite=None; Secure';HTTPS
基本概念
HTTPS(Hypertext Transfer Protocol Secure)是HTTP的安全版本,使用SSL/TLS加密通信。
HTTPS优势
- 加密通信,防止中间人攻击
- 验证服务器身份,防止钓鱼网站
- 保证数据完整性,防止数据篡改
HTTPS配置
nginx
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
}面试常见问题
1. 什么是同源策略?
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
2. 什么是CORS?
CORS(跨域资源共享)是一种机制,允许服务器声明哪些源可以访问资源。
3. 什么是XSS攻击?
XSS(Cross-Site Scripting)跨站脚本攻击,攻击者在网页中注入恶意脚本。
4. 如何防止XSS攻击?
- 输入验证
- 输出编码
- 使用textContent
- 使用CSP
5. 什么是CSRF攻击?
CSRF(Cross-Site Request Forgery)跨站请求伪造,攻击者诱使用户在已认证的网站上执行非预期操作。
通过理解浏览器安全机制的各种技术和最佳实践,可以创建更安全的Web应用。