neocrates 0.1.47

A comprehensive Rust library for various utilities and helpers
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# Captcha Service Module

这个模块提供了多种验证码的生成和验证功能,支持滑动验证码、数字验证码和字母数字验证码。

## 功能特性

### 支持的验证码类型

1. **滑动验证码 (Slider Captcha)** - 用于滑动验证场景
2. **数字验证码 (Numeric Captcha)** - 4-8 位纯数字验证码
3. **字母数字验证码 (Alphanumeric Captcha)** - 4-10 位字母+数字组合(排除易混淆字符)

## 快速开始

### 前置要求

确保你的项目启用了 `web` 和 `redis` features:

```toml
[dependencies]
neocrates = { version = "0.1", features = ["web", "redis"] }
```

### 环境准备

1. **启动 Redis 服务**
```bash
# macOS/Linux
redis-server

# Docker
docker run -d -p 6379:6379 redis:latest
```

2. **设置环境变量**(可选):

```bash
export REDIS_URL="redis://127.0.0.1:6379"
```

## 使用示例

### 1. 数字验证码

#### 生成验证码

```rust
use neocrates::captcha::CaptchaService;
use neocrates::rediscache::{RedisPool, RedisConfig};
use std::sync::Arc;

#[tokio::main]
async fn main() {
    // 初始化 Redis
    let config = RedisConfig {
        url: "redis://127.0.0.1:6379".to_string(),
        max_size: 10,
        min_idle: Some(1),
        connection_timeout: std::time::Duration::from_secs(5),
        idle_timeout: Some(std::time::Duration::from_secs(600)),
        max_lifetime: Some(std::time::Duration::from_secs(3600)),
    };

    let redis_pool = Arc::new(RedisPool::new(config).await.unwrap());

    // 生成 6 位数字验证码
    let captcha = CaptchaService::gen_numeric_captcha(
        &redis_pool,
        "user@example.com",  // 账户标识
        Some(6)               // 验证码长度
    ).await.unwrap();

    println!("验证码 ID: {}", captcha.id);
    println!("验证码内容: {}", captcha.code);
    println!("有效期: {} 秒", captcha.expires_in);
}
```

#### 验证验证码

```rust
// 验证用户输入的验证码
let result = CaptchaService::validate_numeric_captcha(
    &redis_pool,
    &captcha_id,     // 验证码 ID
    "123456",        // 用户输入的验证码
    true             // 验证成功后是否删除
).await;

match result {
    Ok(_) => println!("验证成功!"),
    Err(e) => println!("验证失败: {}", e),
}
```

### 2. 字母数字验证码

```rust
// 生成字母数字验证码(排除易混淆字符如 0/O, 1/I/l)
let captcha = CaptchaService::gen_alphanumeric_captcha(
    &redis_pool,
    "user@example.com",
    Some(6)  // 6 位验证码
).await.unwrap();

println!("验证码: {}", captcha.code);  // 例如: "A3K7M9"

// 验证(不区分大小写)
let result = CaptchaService::validate_alphanumeric_captcha(
    &redis_pool,
    &captcha.id,
    "a3k7m9",  // 小写也可以
    true
).await;
```

### 3. 滑动验证码

```rust
// 生成滑动验证码
CaptchaService::gen_captcha_slider(
    &redis_pool,
    "abc123",            // 滑动验证码(由前端计算)
    "user@example.com"   // 账户标识
).await.unwrap();

// 验证滑动验证码
let result = CaptchaService::captcha_slider_valid(
    &redis_pool,
    "abc123",            // 用户输入的验证码
    "user@example.com",  // 账户标识
    true                 // 验证成功后删除
).await;
```

### 4. 手动删除验证码

```rust
// 删除滑动验证码
CaptchaService::captcha_slider_delete(
    &redis_pool,
    "user@example.com"
).await.unwrap();
```

## 运行示例应用

### 启动示例服务器

```bash
cargo run --example captcha_example --features web,redis
```

服务器将在 `http://127.0.0.1:3000` 启动。

### API 端点

| 方法 | 路径                                 | 描述               |
| ---- | ------------------------------------ | ------------------ |
| GET  | `/`                                  | 健康检查           |
| POST | `/api/captcha/numeric/generate`      | 生成数字验证码     |
| POST | `/api/captcha/numeric/validate`      | 验证数字验证码     |
| POST | `/api/captcha/alphanumeric/generate` | 生成字母数字验证码 |
| POST | `/api/captcha/alphanumeric/validate` | 验证字母数字验证码 |
| POST | `/api/captcha/slider/generate`       | 生成滑动验证码     |
| POST | `/api/captcha/slider/validate`       | 验证滑动验证码     |

## 测试示例

### 1. 生成数字验证码

```bash
curl -X POST http://localhost:3000/api/captcha/numeric/generate \
  -H "Content-Type: application/json" \
  -d '{
    "account": "user@example.com",
    "length": 6
  }'
```

**响应示例**:

```json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "code": "123456",
    "expires_in": 120
  },
  "message": "Numeric captcha generated successfully"
}
```

### 2. 验证数字验证码

```bash
curl -X POST http://localhost:3000/api/captcha/numeric/validate \
  -H "Content-Type: application/json" \
  -d '{
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "code": "123456"
  }'
```

**成功响应**:

```json
{
  "success": true,
  "data": "Valid",
  "message": "Captcha validation successful"
}
```

**失败响应**:

```json
{
  "success": false,
  "data": null,
  "message": "Captcha validation failed: Numeric captcha verification failed"
}
```

### 3. 生成字母数字验证码

```bash
curl -X POST http://localhost:3000/api/captcha/alphanumeric/generate \
  -H "Content-Type: application/json" \
  -d '{
    "account": "user@example.com",
    "length": 6
  }'
```

**响应示例**:

```json
{
  "success": true,
  "data": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "code": "A3K7M9",
    "expires_in": 120
  },
  "message": "Alphanumeric captcha generated successfully"
}
```

### 4. 验证字母数字验证码(不区分大小写)

```bash
curl -X POST http://localhost:3000/api/captcha/alphanumeric/validate \
  -H "Content-Type: application/json" \
  -d '{
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "code": "a3k7m9"
  }'
```

### 5. 生成滑动验证码

```bash
curl -X POST http://localhost:3000/api/captcha/slider/generate \
  -H "Content-Type: application/json" \
  -d '{
    "account": "user@example.com",
    "code": "abc123"
  }'
```

### 6. 验证滑动验证码

```bash
curl -X POST http://localhost:3000/api/captcha/slider/validate \
  -H "Content-Type: application/json" \
  -d '{
    "account": "user@example.com",
    "code": "abc123"
  }'
```

## 配置说明

### Redis 配置

```rust
use neocrates::rediscache::RedisConfig;

let config = RedisConfig {
    url: "redis://127.0.0.1:6379".to_string(),
    max_size: 10,                                           // 连接池最大连接数
    min_idle: Some(1),                                      // 最小空闲连接数
    connection_timeout: std::time::Duration::from_secs(5),  // 连接超时
    idle_timeout: Some(std::time::Duration::from_secs(600)), // 空闲超时(10分钟)
    max_lifetime: Some(std::time::Duration::from_secs(3600)), // 最大生命周期(1小时)
};
```

### 验证码配置

验证码默认有效期为 **120 秒(2 分钟)**。

可以通过修改 `CaptchaService::DEFAULT_EXPIRATION` 常量来调整。

## 数据结构

### CaptchaData

```rust
pub struct CaptchaData {
    /// 验证码 ID(用于后续验证)
    pub id: String,

    /// 验证码内容(实际的验证码值)
    pub code: String,

    /// 有效期(秒)
    pub expires_in: u64,
}
```

### CaptchaType

```rust
pub enum CaptchaType {
    /// 滑动验证码
    Slider,

    /// 数字验证码(4-8 位)
    Numeric,

    /// 字母数字验证码(4-10 位)
    Alphanumeric,
}
```

## Redis 存储键格式

- **数字验证码**: `captcha:numeric:{id}`
- **字母数字验证码**: `captcha:alpha:{id}`
- **滑动验证码**: `captcha:slider:{account}`

## 安全性说明

1. **哈希存储**:滑动验证码使用 MD5 哈希存储,防止明文泄露
2. **自动过期**:所有验证码默认 120 秒后自动过期
3. **一次性使用**:验证成功后可选择立即删除(推荐)
4. **字符排除**:字母数字验证码排除易混淆字符(0/O, 1/I/l)

## 最佳实践

### 1. 生成验证码时

```rust
// ✅ 推荐:记录验证码 ID,不要返回验证码内容给前端
let captcha = CaptchaService::gen_numeric_captcha(&redis_pool, account, Some(6)).await?;

// 只返回 ID 给前端
return Json(json!({
    "captcha_id": captcha.id,
    "expires_in": captcha.expires_in
}));
```

### 2. 验证验证码时

```rust
// ✅ 推荐:验证成功后立即删除
CaptchaService::validate_numeric_captcha(
    &redis_pool,
    &id,
    &code,
    true  // 删除验证码,防止重复使用
).await?;
```

### 3. 错误处理

```rust
match CaptchaService::validate_numeric_captcha(&redis_pool, &id, &code, true).await {
    Ok(_) => {
        // 验证成功,继续后续流程
    }
    Err(AppError::ClientError(msg)) => {
        // 客户端错误(验证码错误、已过期等)
        return Err(StatusCode::BAD_REQUEST);
    }
    Err(AppError::RedisError(msg)) => {
        // Redis 错误(连接失败等)
        return Err(StatusCode::INTERNAL_SERVER_ERROR);
    }
    Err(_) => {
        // 其他错误
        return Err(StatusCode::INTERNAL_SERVER_ERROR);
    }
}
```

### 4. 与 Axum 集成

```rust
use neocrates::axum::{Router, routing::post, extract::State};
use neocrates::captcha::CaptchaService;
use std::sync::Arc;

#[derive(Clone)]
struct AppState {
    redis_pool: Arc<RedisPool>,
}

async fn generate_captcha(
    State(state): State<AppState>,
    Json(req): Json<GenerateRequest>,
) -> Result<Json<CaptchaData>, StatusCode> {
    CaptchaService::gen_numeric_captcha(&state.redis_pool, &req.account, Some(6))
        .await
        .map(Json)
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}

let app = Router::new()
    .route("/captcha/generate", post(generate_captcha))
    .with_state(AppState { redis_pool });
```

## 常见问题

### Q: 验证码总是验证失败?

A: 检查以下几点:

1. Redis 是否正常运行
2. 验证码是否已过期(默认 120 秒)
3. 验证码 ID 是否正确
4. 字母数字验证码是否大小写匹配(不区分大小写)

### Q: 如何调整验证码有效期?

A: 修改 `CaptchaService::DEFAULT_EXPIRATION` 常量,或在生成时自定义过期时间。

### Q: 如何自定义验证码长度?

A: 在调用生成函数时传入 `Some(length)` 参数:

```rust
// 生成 8 位数字验证码
let captcha = CaptchaService::gen_numeric_captcha(&redis_pool, account, Some(8)).await?;
```

### Q: 验证码可以重复使用吗?

A: 不推荐。验证时将 `delete` 参数设置为 `true` 可以确保验证码只能使用一次。

### Q: 如何处理并发验证?

A: Redis 操作是原子性的,多个请求同时验证同一个验证码时,只有第一个会成功(如果启用了删除)。

## 性能建议

1. **连接池大小**:根据并发量调整 `max_size`,推荐值为 10-50
2. **批量操作**:如果需要批量生成验证码,考虑使用 Pipeline
3. **监控**:监控 Redis 连接池使用情况和验证码验证失败率

## 相关资源

- [Axum 官方文档]https://docs.rs/axum/
- [Redis 文档]https://redis.io/documentation
- [Neocrates 完整文档]https://docs.rs/neocrates/

## 许可证

MIT OR Apache-2.0