Files
java-10561/docs/QrCode_Two_Modes_Explanation.md
2025-09-06 11:58:18 +08:00

198 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 二维码加密的两种模式详解
## 问题背景
您提出的问题很关键:**用户生成二维码时的token和门店核销时的token是否一样**
在实际业务场景中,这确实是个问题。我们提供了两种解决方案:
## 模式一自包含模式Self-Contained Mode
### 特点
- 二维码**包含所有解密所需的信息**
- 扫码方**无需额外的密钥或token**
- 适用于**点对点**的场景
### 工作流程
```
1. 用户生成二维码
2. 系统生成随机token作为密钥
3. 用token加密数据
4. 二维码内容 = {token, 加密数据, 类型}
5. 任何人扫码都能解密因为token在二维码中
```
### 二维码内容示例
```json
{
"token": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"data": "encrypted_data_here",
"type": "encrypted"
}
```
### 使用场景
- 临时分享链接
- 个人信息展示
- 一次性验证码
### 安全性
- ✅ 数据加密保护
- ✅ 支持过期时间
- ⚠️ 任何人扫码都能解密
- ⚠️ 二维码泄露 = 数据泄露
---
## 模式二业务模式Business Mode
### 特点
- 使用**统一的业务密钥**
- 门店有**预设的解密密钥**
- 支持**防重复核销**
- 适用于**商业核销**场景
### 工作流程
```
1. 用户生成二维码
2. 使用预设的业务密钥(如门店密钥)加密
3. 生成唯一的二维码ID
4. 二维码内容 = {二维码ID, 加密数据, 类型}
5. 门店用相同的业务密钥解密
6. 系统标记该二维码为已使用
```
### 二维码内容示例
```json
{
"qrId": "abc123def456",
"data": "encrypted_data_here",
"type": "business_encrypted",
"expire": "1692345678000"
}
```
### 密钥管理
```
门店A: businessKey = "store_001_secret_key"
门店B: businessKey = "store_002_secret_key"
门店C: businessKey = "store_003_secret_key"
```
### 使用场景
- 🎫 **优惠券核销**
- 🍔 **餐厅点餐码**
- 🎬 **电影票验证**
- 🚗 **停车场进出**
- 💊 **药品溯源**
### 安全性
- ✅ 数据加密保护
- ✅ 防重复核销
- ✅ 门店权限控制
- ✅ 即使二维码泄露,没有密钥也无法解密
---
## 实际应用示例
### 场景:餐厅点餐系统
#### 1. 用户下单生成二维码
```java
// 用户订单信息
String orderData = "orderId:12345,tableNo:8,amount:88.50";
// 使用餐厅的业务密钥
String restaurantKey = "restaurant_001_secret";
// 生成业务加密二维码
Map<String, Object> result = encryptedQrCodeUtil.generateBusinessEncryptedQrCode(
orderData, 300, 300, restaurantKey, 60L
);
```
#### 2. 服务员扫码核销
```java
// 扫码得到的内容
String qrContent = "{\"qrId\":\"abc123\",\"data\":\"encrypted...\",\"type\":\"business_encrypted\"}";
// 使用餐厅密钥解密
String orderInfo = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey(
qrContent, "restaurant_001_secret"
);
// 结果orderId:12345,tableNo:8,amount:88.50
```
#### 3. 防重复核销
```java
// 第二次扫同一个二维码
try {
String orderInfo = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey(
qrContent, "restaurant_001_secret"
);
} catch (RuntimeException e) {
// 抛出异常:二维码已被使用
}
```
---
## API接口对比
### 自包含模式
```http
# 生成
POST /api/qr-code/create-encrypted-qr-code
data=user_info&width=200&height=200&expireMinutes=30
# 解密(任何人都可以)
POST /api/qr-code/verify-and-decrypt-qr
qrContent={"token":"...","data":"...","type":"encrypted"}
```
### 业务模式
```http
# 生成
POST /api/qr-code/create-business-encrypted-qr-code
data=order_info&businessKey=store_001_key&width=200&height=200&expireMinutes=60
# 核销(需要对应的业务密钥)
POST /api/qr-code/verify-business-qr
qrContent={"qrId":"...","data":"...","type":"business_encrypted"}&businessKey=store_001_key
```
---
## 选择建议
| 场景 | 推荐模式 | 原因 |
|------|----------|------|
| 个人信息分享 | 自包含模式 | 简单方便,无需额外配置 |
| 临时链接分享 | 自包含模式 | 接收方无需特殊权限 |
| 商业核销 | 业务模式 | 安全性高,防重复使用 |
| 门店验证 | 业务模式 | 权限控制,业务流程完整 |
| 支付码 | 业务模式 | 安全要求高 |
| 会员卡 | 业务模式 | 需要权限验证 |
---
## 总结
**您的疑问是对的!** 在门店核销场景中:
1. **自包含模式**token在二维码中门店直接扫码即可解密
2. **业务模式**:门店有预设的业务密钥,用户生成时用这个密钥加密
**推荐使用业务模式**,因为它更符合实际的商业应用需求,安全性更高,且支持防重复核销。