File size: 2,421 Bytes
7fc5208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * 生成 JWT token
 * @param username 用户名
 * @param secret 密钥
 * @returns 生成的 token 字符串
 */
export async function generateToken(username: string, secret: string): Promise<string> {
    // JWT 头部信息
    const header = { alg: 'HS256', typ: 'JWT' };
    // JWT 载荷信息
    const payload = {
      sub: username,
      exp: Math.floor(Date.now() / 1000) + (30 * 24 * 60 * 60), //30天后过期
      iat: Math.floor(Date.now() / 1000) // 签发时间
    };
  
    const encodedHeader = btoa(JSON.stringify(header));
    const encodedPayload = btoa(JSON.stringify(payload));
    const signature = await createHmacSignature(
      `${encodedHeader}.${encodedPayload}`,
      secret
    );
  
    return `${encodedHeader}.${encodedPayload}.${signature}`;
  }
  
  /**
   * 验证 JWT token
   * @param request 请求对象
   * @param secret 密钥
   * @returns 验证是否通过
   */
  export async function verifyToken(request: Request, secret: string): Promise<boolean> {
    const authHeader = request.headers.get('Authorization');
    if (!authHeader?.startsWith('Bearer ')) {
      return false;
    }
  
    const token = authHeader.split(' ')[1];
    try {
      const [headerB64, payloadB64, signatureB64] = token.split('.');
      const expectedSignature = await createHmacSignature(
        `${headerB64}.${payloadB64}`,
        secret
      );
  
      if (signatureB64 !== expectedSignature) {
        return false;
      }
  
      const payload = JSON.parse(atob(payloadB64));
      const now = Math.floor(Date.now() / 1000);
  
      return payload.exp > now;
    } catch (error) {
      console.error('Token verification failed:', error);
      return false;
    }
  }
  
  /**
   * 创建 HMAC 签名
   * @param message 需要签名的消息
   * @param secret 密钥
   * @returns 签名字符串
   */
  async function createHmacSignature(message: string, secret: string): Promise<string> {
    const encoder = new TextEncoder();
    const keyData = encoder.encode(secret);
    const messageData = encoder.encode(message);
  
    const cryptoKey = await crypto.subtle.importKey(
      'raw',
      keyData,
      { name: 'HMAC', hash: 'SHA-256' },
      false,
      ['sign']
    );
  
    const signature = await crypto.subtle.sign(
      'HMAC',
      cryptoKey,
      messageData
    );
  
    return btoa(String.fromCharCode(...new Uint8Array(signature)));
  }