vault backup: 2026-04-25 16:06:25

This commit is contained in:
2026-04-25 16:06:25 +08:00
parent 70a6e3d4ea
commit f6ee499fa7
5 changed files with 527 additions and 0 deletions
@@ -0,0 +1,211 @@
---
tags: [go, frontend, security, authentication, login, encryption, assignment]
create time: 2026-04-25 14:30
---
# 登录安全流程:前端与后端的加密协作
## 概述
登录是 Web 应用最敏感的操作之一。本文深入探讨前端和后端各自的安全职责,以及 HTTPS 协议下的标准登录认证流程。
## 核心问题:两端都需要加密吗?
**不完全是。** 更准确的说法是——**传输层加密 + 密码侧哈希**。
> 💡 **想一想**:如果前端把密码用 SHA-256 哈希后再发送,这样后端收到的是哈希值而不是明文密码,是不是更安全?
答案是否定的。因为**哈希后的值本身就是凭证**。攻击者截获这个哈希值后,可以直接重放给后端完成登录——哈希值被截获等于密码被截获。所以业界最主流的做法是:**前端直接发送明文密码,由 HTTPS 保护传输安全**。
## 登录全流程
```mermaid
sequenceDiagram
participant U as 用户
participant F as 前端(React)
participant S as 后端(Go)
participant DB as 数据库
U->>F: 输入用户名 + 密码
F->>S: POST /api/login (HTTPS)
Note over S: 传输层 TLS 加密
S->>DB: SELECT * FROM users WHERE username=?
DB-->>S: 用户记录 (hashed_password)
S->>S: bcrypt.Compare(password, stored_hash)
alt 密码正确
S->>S: 生成 JWT Token
S-->>F: {access_token, expires_in}
F->>F: 保存 Token (Memory/LocalStorage)
F-->>U: 跳转首页 ✓
else 密码错误
S-->>F: 401 Unauthorized
F-->>U: 提示"用户名或密码错误"
end
```
## 三层安全模型
登录安全分为三个层次,每层由不同方负责:
### 第一层:传输加密(HTTPS/TLS)
**谁负责**:服务器端配置,前端透明使用
```
HTTP (明文) → HTTPS (TLS 加密)
password = "123456" → TLS 密文传输
```
- 所有请求自动加密,中间人无法窃取
- 前端只需使用 `https://` 前缀的 API 地址
- 这是**必须的**,没有替代方案
### 第二层:密码存储加密(后端)
**谁负责**:后端
```go
package auth
import "golang.org/x/crypto/bcrypt"
// 注册时:密码哈希后存入数据库
func Register(username, password string) error {
hash, err := bcrypt.GenerateFromPassword(
[]byte(password), bcrypt.DefaultCost,
)
// 默认成本因子 = 10(详见 [[金山办公作业/Week06/bcrypt成本因子]])
if err != nil {
return err
}
// 存入数据库的是 hash,不是 password
return db.InsertUser(username, string(hash))
}
// 登录时:比对输入的密码与存储的哈希
func Login(username, password string) (string, error) {
user, err := db.GetUser(username)
if err != nil {
return "", ErrUserNotFound
}
if err := bcrypt.CompareHashAndPassword(
[]byte(user.HashedPassword), []byte(password),
); err != nil {
return "", ErrWrongPassword
}
// 验证通过 → 签发 Token
return generateJWT(user), nil
}
```
默认成本因子 = 10(详见 [[金山办公作业/Week06/bcrypt成本因子]])
**为什么用 bcrypt?**
- 自动加盐,相同密码在不同用户哈希结果不同
- 计算成本可调,抵御暴力破解
- 比 MD5/SHA-256 更适合密码哈希
### 第三层:认证凭据管理(前后端协作)
**谁负责**:前后端共同
```go
// 后端签发 JWT
func generateJWT(userID string, username string) string {
claims := jwt.MapClaims{
"user_id": userID,
"username": username,
"exp": time.Now().Add(2 * time.Hour).Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secretKey)
}
```
```typescript
// 前端登录后存储 Token
async function handleLogin(username: string, password: string) {
const resp = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password }),
});
if (resp.ok) {
const data = await resp.json();
// 方式1:Memory(更安全,刷新后失效)
sessionStorage.setItem('token', data.access_token);
// 方式2:LocalStorage(持久登录)
localStorage.setItem('token', data.access_token);
router.push('/dashboard');
}
}
```
## 前端是否需要额外加密?
| 方案 | 前端做哈希? | 安全性 | 复杂度 | 推荐度 |
|------|------------|--------|--------|--------|
| **标准方案** ✅ | ❌ 不加密,直接发 | 高(HTTPS 保护) | 低 | ⭐⭐⭐⭐⭐ |
| 前端 SHA-256 | ✅ 哈希后发送 | 中(哈希值可重放) | 中 | ⭐⭐ |
| 客户端密钥派生 | ✅ PBKDF2/Argon2 | 更高 | 高 | ⭐⭐⭐ |
**为什么标准方案最优?**
```
方案A(前端不加密):
前端明文 → HTTPS加密传输 → 后端验证 bcrypt 哈希
✅ 中间人看不到密码
方案B(前端加 SHA-256):
前端 SHA-256(password) → 密文传输 → 后端比对 SHA-256
❌ 中间人截获哈希值 → 直接重放登录(哈希=密码)
```
**结论**:前端额外哈希不仅不能提升安全性,反而引入了"重放攻击"风险。
## 进阶:高安全场景下的前端处理
对于金融类应用等高安全需求场景,可以采用客户端密钥派生方案——前端在发送密码之前,先用后端下发的随机盐值做 PBKDF2 派生,让传输层上永远不出现原始密码。
详细流程请见:[[金山办公作业/Week06/客户端密钥派生]]
## 最佳实践清单
### 前端
✅ **推荐**
- 使用 HTTPS 地址调用 API
- 登录后 Token 存储在内存(sessionStorage)
- 密码输入框使用 `<input type="password">`(防误看)
- 登录失败后清空密码输入框
- 设置合理的 Token 过期时间(2h ~ 24h)
❌ **避免**
- 在 URL 参数中传递密码
- 用 localStorage 存明文密码
- 登录失败后暴露具体原因("用户名不存在" vs "密码错误")——统一提示"用户名或密码错误"
- 前端对密码做 SHA-256 哈希
### 后端
✅ **推荐**
- 使用 bcrypt/argon2 哈希存储密码
- 统一返回模糊错误信息(防止用户名枚举)
- 添加登录频率限制(防暴力破解)
- JWT 设置短期过期 + Refresh Token 机制
- 密钥通过环境变量管理,不写死代码
❌ **避免**
- 明文存储密码
- 使用 MD5/SHA-256 哈希密码
- 错误信息暴露过多细节
## 关联笔记
- [[金山办公作业/Week05/用户认证.md]] - Go 用户认证完整实现
- [[金山办公作业/Week06/客户端密钥派生]] - 客户端密钥派生(盐值挑战)详解
- [[CS/NET/HTTPS]] - HTTPS/TLS 原理
- [[CS/DB/SQL安全]] - 密码安全存储