generateRefreshToken 生成并存储Refresh Token
(ctx context.Context, user *User, familyID string)
| 1470 | |
| 1471 | // generateRefreshToken 生成并存储Refresh Token |
| 1472 | func (s *AuthService) generateRefreshToken(ctx context.Context, user *User, familyID string) (string, error) { |
| 1473 | // 生成随机Token |
| 1474 | tokenBytes := make([]byte, 32) |
| 1475 | if _, err := rand.Read(tokenBytes); err != nil { |
| 1476 | return "", fmt.Errorf("generate random bytes: %w", err) |
| 1477 | } |
| 1478 | rawToken := refreshTokenPrefix + hex.EncodeToString(tokenBytes) |
| 1479 | |
| 1480 | // 计算Token哈希(存储哈希而非原始Token) |
| 1481 | tokenHash := hashToken(rawToken) |
| 1482 | |
| 1483 | // 如果没有提供familyID,生成新的 |
| 1484 | if familyID == "" { |
| 1485 | familyBytes := make([]byte, 16) |
| 1486 | if _, err := rand.Read(familyBytes); err != nil { |
| 1487 | return "", fmt.Errorf("generate family id: %w", err) |
| 1488 | } |
| 1489 | familyID = hex.EncodeToString(familyBytes) |
| 1490 | } |
| 1491 | |
| 1492 | now := time.Now() |
| 1493 | ttl := time.Duration(s.cfg.JWT.RefreshTokenExpireDays) * 24 * time.Hour |
| 1494 | |
| 1495 | data := &RefreshTokenData{ |
| 1496 | UserID: user.ID, |
| 1497 | TokenVersion: resolvedTokenVersion(user), |
| 1498 | FamilyID: familyID, |
| 1499 | CreatedAt: now, |
| 1500 | ExpiresAt: now.Add(ttl), |
| 1501 | } |
| 1502 | |
| 1503 | // 存储Token数据 |
| 1504 | if err := s.refreshTokenCache.StoreRefreshToken(ctx, tokenHash, data, ttl); err != nil { |
| 1505 | return "", fmt.Errorf("store refresh token: %w", err) |
| 1506 | } |
| 1507 | |
| 1508 | // 添加到用户Token集合 |
| 1509 | if err := s.refreshTokenCache.AddToUserTokenSet(ctx, user.ID, tokenHash, ttl); err != nil { |
| 1510 | logger.LegacyPrintf("service.auth", "[Auth] Failed to add token to user set: %v", err) |
| 1511 | // 不影响主流程 |
| 1512 | } |
| 1513 | |
| 1514 | // 添加到家族Token集合 |
| 1515 | if err := s.refreshTokenCache.AddToFamilyTokenSet(ctx, familyID, tokenHash, ttl); err != nil { |
| 1516 | logger.LegacyPrintf("service.auth", "[Auth] Failed to add token to family set: %v", err) |
| 1517 | // 不影响主流程 |
| 1518 | } |
| 1519 | |
| 1520 | return rawToken, nil |
| 1521 | } |
| 1522 | |
| 1523 | // RefreshTokenPair 使用Refresh Token刷新Token对 |
| 1524 | // 实现Token轮转:每次刷新都会生成新的Refresh Token,旧Token立即失效 |
no test coverage detected