blessing-skin-server/database/migrations/2026_01_24_000001_split_signature_fields.php
shhzhang 3d42aab16d [Security] Dynamic Email Verification & Password Reset Links
**Problem**
1. **Static Signature Vulnerability**:
   - Email verification links used a static signature algorithm (same link for lifetime), allowing account hijacking if links were leaked.
   - *Worst-case scenario*: Compromised AppKey + leaked link → full-site account under danger.
2. **Overly Long Reset Window**:
   - Password reset links remained valid for 1 hour, enabling attackers to hijack accounts if intercepted.
   - *Worst-case scenario*: Compromised AppKey + leaked link → full-site account account take over.

 **Solution**
- **Email Verification**:
  - Replaced static signatures with **HMAC-SHA256 + timestamp + nonce**.
  - Links are now **one-time-use** and expire immediately after verification.
- **Password Reset**:
  - Reduced validity window from 1h → **5 minutes**.
  - Added rate limiting to prevent brute-force attacks.

 **Impact**
- **Closed Communities**: Critical for real-name systems (e.g., gaming, enterprise).
- **AppKey Leak Mitigation**: Even with leaked AppKey, intercepted links are now useless.

The commit message is translated by Deepseek due to my poor English.
2026-01-24 23:16:39 +08:00

40 lines
1.5 KiB
PHP

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class SplitSignatureFields extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
// 移除之前添加的通用字段
$table->dropColumn(['verification_signature', 'signature_expires_at']);
// 添加密码重置专用字段
$table->string('password_reset_signature')->nullable()->after('verified');
$table->timestamp('password_reset_expires_at')->nullable()->after('password_reset_signature');
// 添加邮箱验证专用字段
$table->string('email_verification_signature')->nullable()->after('password_reset_expires_at');
$table->timestamp('email_verification_expires_at')->nullable()->after('email_verification_signature');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
// 删除新添加的独立字段
$table->dropColumn([
'password_reset_signature',
'password_reset_expires_at',
'email_verification_signature',
'email_verification_expires_at'
]);
// 恢复之前的通用字段
$table->string('verification_signature')->nullable();
$table->timestamp('signature_expires_at')->nullable();
});
}
}