diff --git a/server/MiAssessment/src/MiAssessment.Core/Services/AuthService.cs b/server/MiAssessment/src/MiAssessment.Core/Services/AuthService.cs
index 4123f7e..ddfaa14 100644
--- a/server/MiAssessment/src/MiAssessment.Core/Services/AuthService.cs
+++ b/server/MiAssessment/src/MiAssessment.Core/Services/AuthService.cs
@@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace MiAssessment.Core.Services;
///
-/// ��֤����ʵ��
+/// 认证服务实现
///
public class AuthService : IAuthService
{
@@ -30,7 +30,7 @@ public class AuthService : IAuthService
private const string SmsCodeKeyPrefix = "sms:code:";
private const int DebounceSeconds = 3;
- // Refresh Token ����
+ // Refresh Token 长度
private const int RefreshTokenLength = 64;
public AuthService(
@@ -57,44 +57,44 @@ public class AuthService : IAuthService
///
- /// ��С�����¼
+ /// 微信小程序登录
/// Requirements: 1.1-1.8
///
public async Task WechatMiniProgramLoginAsync(string code, int? pid, string? clickId, string? phoneCode = null)
{
- _logger.LogInformation("[AuthService] �ŵ�¼��ʼ��code={Code}, pid={Pid}, hasPhoneCode={HasPhoneCode}", code, pid, !string.IsNullOrWhiteSpace(phoneCode));
+ _logger.LogInformation("[AuthService] 微信登录开始,code={Code}, pid={Pid}, hasPhoneCode={HasPhoneCode}", code, pid, !string.IsNullOrWhiteSpace(phoneCode));
if (string.IsNullOrWhiteSpace(code))
{
- _logger.LogWarning("[AuthService] �ŵ�¼ʧ�ܣ�codeΪ��");
+ _logger.LogWarning("[AuthService] 微信登录失败,code为空");
return new LoginResult
{
Success = false,
- ErrorMessage = "��Ȩcode����Ϊ��"
+ ErrorMessage = "授权code不能为空"
};
}
try
{
- // 1.6 �������� - 3���ڲ������ظ���¼
+ // 1.6 防抖处理 - 3秒内不允许重复登录
var debounceKey = $"{LoginDebounceKeyPrefix}wechat:{code}";
- _logger.LogInformation("[AuthService] ��������: {Key}", debounceKey);
+ _logger.LogInformation("[AuthService] 防抖检查: {Key}", debounceKey);
var lockAcquired = await _redisService.TryAcquireLockAsync(debounceKey, "1", TimeSpan.FromSeconds(DebounceSeconds));
if (!lockAcquired)
{
- _logger.LogWarning("[AuthService] �����������ܾ��ظ���¼����: {Code}", code);
+ _logger.LogWarning("[AuthService] 防抖处理:拒绝重复登录请求: {Code}", code);
return new LoginResult
{
Success = false,
- ErrorMessage = "����Ƶ����¼"
+ ErrorMessage = "请勿频繁登录"
};
}
- _logger.LogInformation("[AuthService] ��������ȡ�ɹ�");
+ _logger.LogInformation("[AuthService] 防抖锁获取成功");
- // 1.1 ������API��ȡopenid��unionid
- _logger.LogInformation("[AuthService] ��ʼ������API��ȡopenid...");
+ // 1.1 调用微信API获取openid和unionid
+ _logger.LogInformation("[AuthService] 开始调用微信API获取openid...");
var wechatResult = await _wechatService.GetOpenIdAsync(code);
- _logger.LogInformation("[AuthService] ��API������ɣ�Success={Success}, OpenId={OpenId}, UnionId={UnionId}, Error={Error}",
+ _logger.LogInformation("[AuthService] 微信API调用完成:Success={Success}, OpenId={OpenId}, UnionId={UnionId}, Error={Error}",
wechatResult.Success,
wechatResult.OpenId ?? "null",
wechatResult.UnionId ?? "null",
@@ -102,30 +102,30 @@ public class AuthService : IAuthService
if (!wechatResult.Success)
{
- _logger.LogWarning("[AuthService] ��API����ʧ��: {Error}", wechatResult.ErrorMessage);
+ _logger.LogWarning("[AuthService] 微信API调用失败: {Error}", wechatResult.ErrorMessage);
return new LoginResult
{
Success = false,
- ErrorMessage = wechatResult.ErrorMessage ?? "��¼ʧ�ܣ����Ժ�����"
+ ErrorMessage = wechatResult.ErrorMessage ?? "登录失败,请稍后重试"
};
}
var openId = wechatResult.OpenId!;
var unionId = wechatResult.UnionId;
- // 1.2 �����û� - ����ͨ��unionid���ң����ͨ��openid����
+ // 1.2 查找用户 - 优先通过unionid查找,再通过openid查找
User? user = null;
if (!string.IsNullOrWhiteSpace(unionId))
{
- _logger.LogInformation("[AuthService] ����ͨ��unionid�����û�: {UnionId}", unionId);
+ _logger.LogInformation("[AuthService] 尝试通过unionid查找用户: {UnionId}", unionId);
user = await _userService.GetUserByUnionIdAsync(unionId);
- _logger.LogInformation("[AuthService] unionid���ҽ��: {Found}", user != null ? $"�ҵ��û�ID={user.Id}" : "δ�ҵ�");
+ _logger.LogInformation("[AuthService] unionid查找结果: {Found}", user != null ? $"找到用户ID={user.Id}" : "未找到");
}
if (user == null)
{
- _logger.LogInformation("[AuthService] ����ͨ��openid�����û�: {OpenId}", openId);
+ _logger.LogInformation("[AuthService] 尝试通过openid查找用户: {OpenId}", openId);
user = await _userService.GetUserByOpenIdAsync(openId);
- _logger.LogInformation("[AuthService] openid���ҽ��: {Found}", user != null ? $"�ҵ��û�ID={user.Id}" : "δ�ҵ�");
+ _logger.LogInformation("[AuthService] openid查找结果: {Found}", user != null ? $"找到用户ID={user.Id}" : "未找到");
}
if (user == null)
@@ -189,36 +189,42 @@ public class AuthService : IAuthService
}
}
- // 1.5 ����˫ Token��Access Token + Refresh Token��
- _logger.LogInformation("[AuthService] ��ʼ����˫ Token: UserId={UserId}", user.Id);
+ // 1.5 生成双 Token(Access Token + Refresh Token)
+ _logger.LogInformation("[AuthService] 开始生成双 Token: UserId={UserId}", user.Id);
var loginResponse = await GenerateLoginResponseAsync(user, null);
- _logger.LogInformation("[AuthService] ˫ Token ���ɳɹ���AccessToken����={Length}", loginResponse.AccessToken?.Length ?? 0);
- _logger.LogInformation("[AuthService] �ŵ�¼�ɹ�: UserId={UserId}", user.Id);
+ // 更新最后登录时间
+ user.LastLoginTime = DateTime.Now;
+ _dbContext.Users.Update(user);
+ await _dbContext.SaveChangesAsync();
+
+ _logger.LogInformation("[AuthService] 双 Token 生成成功,AccessToken长度={Length}", loginResponse.AccessToken?.Length ?? 0);
+
+ _logger.LogInformation("[AuthService] 微信登录成功: UserId={UserId}", user.Id);
return new LoginResult
{
Success = true,
- Token = loginResponse.AccessToken, // ���ݾɰ�
+ Token = loginResponse.AccessToken, // 兼容旧版
UserId = user.Id,
LoginResponse = loginResponse
};
}
catch (Exception ex)
{
- _logger.LogError(ex, "[AuthService] �ŵ�¼�쳣: code={Code}, Message={Message}, StackTrace={StackTrace}",
+ _logger.LogError(ex, "[AuthService] 微信登录异常: code={Code}, Message={Message}, StackTrace={StackTrace}",
code, ex.Message, ex.StackTrace);
return new LoginResult
{
Success = false,
- ErrorMessage = "������ϣ����Ժ�����"
+ ErrorMessage = "服务器异常,请稍后重试"
};
}
}
///
- /// �ֻ�����֤���¼
+ /// 手机号验证码登录
/// Requirements: 2.1-2.7
///
public async Task MobileLoginAsync(string mobile, string code, int? pid, string? clickId)
@@ -228,7 +234,7 @@ public class AuthService : IAuthService
return new LoginResult
{
Success = false,
- ErrorMessage = "�ֻ��Ų���Ϊ��"
+ ErrorMessage = "手机号不能为空"
};
}
@@ -237,13 +243,13 @@ public class AuthService : IAuthService
return new LoginResult
{
Success = false,
- ErrorMessage = "��֤�벻��Ϊ��"
+ ErrorMessage = "验证码不能为空"
};
}
try
{
- // 2.6 �������� - 3���ڲ������ظ���¼
+ // 2.6 防抖处理 - 3秒内不允许重复登录
var debounceKey = $"{LoginDebounceKeyPrefix}mobile:{mobile}";
var lockAcquired = await _redisService.TryAcquireLockAsync(debounceKey, "1", TimeSpan.FromSeconds(DebounceSeconds));
if (!lockAcquired)
@@ -252,11 +258,11 @@ public class AuthService : IAuthService
return new LoginResult
{
Success = false,
- ErrorMessage = "����Ƶ����¼"
+ ErrorMessage = "请勿频繁登录"
};
}
- // 2.1 ��Redis��ȡ����֤��֤��
+ // 2.1 从Redis获取短信验证码验证
var smsCodeKey = $"{SmsCodeKeyPrefix}{mobile}";
var storedCode = await _redisService.GetStringAsync(smsCodeKey);
@@ -266,19 +272,19 @@ public class AuthService : IAuthService
return new LoginResult
{
Success = false,
- ErrorMessage = "��֤�����"
+ ErrorMessage = "验证码错误"
};
}
- // 2.2 ��֤����֤ͨ����ɾ��Redis�е���֤��
+ // 2.2 验证码验证通过,删除Redis中的验证码
await _redisService.DeleteAsync(smsCodeKey);
- // �����û�
+ // 查找用户
var user = await _userService.GetUserByMobileAsync(mobile);
if (user == null)
{
- // 2.3 �û������ڣ��������û�
+ // 2.3 用户不存在,创建新用户
var createDto = new CreateUserDto
{
Mobile = mobile,
@@ -291,15 +297,20 @@ public class AuthService : IAuthService
_logger.LogInformation("New user created via mobile login: UserId={UserId}, Mobile={Mobile}", user.Id, MaskMobile(mobile));
}
- // 2.4 ����˫ Token��Access Token + Refresh Token��
+ // 2.4 生成双 Token(Access Token + Refresh Token)
var loginResponse = await GenerateLoginResponseAsync(user, null);
+ // 更新最后登录时间
+ user.LastLoginTime = DateTime.Now;
+ _dbContext.Users.Update(user);
+ await _dbContext.SaveChangesAsync();
+
_logger.LogInformation("Mobile login successful: UserId={UserId}", user.Id);
return new LoginResult
{
Success = true,
- Token = loginResponse.AccessToken, // ���ݾɰ�
+ Token = loginResponse.AccessToken, // 兼容旧版
UserId = user.Id,
LoginResponse = loginResponse
};
@@ -310,58 +321,58 @@ public class AuthService : IAuthService
return new LoginResult
{
Success = false,
- ErrorMessage = "������ϣ����Ժ�����"
+ ErrorMessage = "服务器异常,请稍后重试"
};
}
}
///
- /// ��֤����ֻ���
+ /// 验证码绑定手机号
/// Requirements: 5.1-5.5
///
public async Task BindMobileAsync(long userId, string mobile, string code)
{
if (string.IsNullOrWhiteSpace(mobile))
{
- throw new ArgumentException("�ֻ��Ų���Ϊ��", nameof(mobile));
+ throw new ArgumentException("手机号不能为空", nameof(mobile));
}
if (string.IsNullOrWhiteSpace(code))
{
- throw new ArgumentException("��֤�벻��Ϊ��", nameof(code));
+ throw new ArgumentException("验证码不能为空", nameof(code));
}
- // 5.1 ��֤������֤��
+ // 5.1 验证短信验证码
var smsCodeKey = $"{SmsCodeKeyPrefix}{mobile}";
var storedCode = await _redisService.GetStringAsync(smsCodeKey);
if (string.IsNullOrWhiteSpace(storedCode) || storedCode != code)
{
_logger.LogWarning("SMS code verification failed for bind mobile: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));
- throw new InvalidOperationException("��֤�����");
+ throw new InvalidOperationException("验证码错误");
}
- // ��֤����֤ͨ����ɾ��
+ // 验证码验证通过,删除
await _redisService.DeleteAsync(smsCodeKey);
- // ��ȡ��ǰ�û�
+ // 获取当前用户
var currentUser = await _userService.GetUserByIdAsync(userId);
if (currentUser == null)
{
- throw new InvalidOperationException("�û�������");
+ throw new InvalidOperationException("用户不存在");
}
- // ����ֻ����Ƿ��ѱ������û���
+ // 检查手机号是否已被其他用户绑定
var existingUser = await _userService.GetUserByMobileAsync(mobile);
if (existingUser != null && existingUser.Id != userId)
{
- // 5.2 �ֻ����ѱ������û�����Ҫ�ϲ��˻�
+ // 5.2 手机号已被其他用户绑定,需要合并账户
return await MergeAccountsAsync(currentUser, existingUser);
}
- // 5.4 �ֻ���δ����ֱ�Ӹ��µ�ǰ�û����ֻ���
+ // 5.4 手机号未被绑定,直接更新当前用户的手机号
await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
_logger.LogInformation("Mobile bound successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));
@@ -369,43 +380,43 @@ public class AuthService : IAuthService
}
///
- /// ����Ȩ���ֻ���
+ /// 微信授权绑定手机号
/// Requirements: 5.1-5.5
///
public async Task WechatBindMobileAsync(long userId, string wechatCode)
{
if (string.IsNullOrWhiteSpace(wechatCode))
{
- throw new ArgumentException("����Ȩcode����Ϊ��", nameof(wechatCode));
+ throw new ArgumentException("微信授权code不能为空", nameof(wechatCode));
}
- // ������API��ȡ�ֻ���
+ // 调用微信API获取手机号
var mobileResult = await _wechatService.GetMobileAsync(wechatCode);
if (!mobileResult.Success || string.IsNullOrWhiteSpace(mobileResult.Mobile))
{
_logger.LogWarning("WeChat get mobile failed: UserId={UserId}, Error={Error}", userId, mobileResult.ErrorMessage);
- throw new InvalidOperationException(mobileResult.ErrorMessage ?? "��ȡ�ֻ���ʧ��");
+ throw new InvalidOperationException(mobileResult.ErrorMessage ?? "获取手机号失败");
}
var mobile = mobileResult.Mobile;
- // ��ȡ��ǰ�û�
+ // 获取当前用户
var currentUser = await _userService.GetUserByIdAsync(userId);
if (currentUser == null)
{
- throw new InvalidOperationException("�û�������");
+ throw new InvalidOperationException("用户不存在");
}
- // ����ֻ����Ƿ��ѱ������û���
+ // 检查手机号是否已被其他用户绑定
var existingUser = await _userService.GetUserByMobileAsync(mobile);
if (existingUser != null && existingUser.Id != userId)
{
- // 5.2 �ֻ����ѱ������û�����Ҫ�ϲ��˻�
+ // 5.2 手机号已被其他用户绑定,需要合并账户
return await MergeAccountsAsync(currentUser, existingUser);
}
- // 5.4 �ֻ���δ����ֱ�Ӹ��µ�ǰ�û����ֻ���
+ // 5.4 手机号未被绑定,直接更新当前用户的手机号
await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
_logger.LogInformation("Mobile bound via WeChat successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));
@@ -414,7 +425,7 @@ public class AuthService : IAuthService
///
- /// ��¼��¼��Ϣ
+ /// 记录登录信息
/// Requirements: 6.1, 6.3, 6.4
///
public async Task RecordLoginAsync(long userId, string? device, string? deviceInfo)
@@ -422,17 +433,17 @@ public class AuthService : IAuthService
var user = await _userService.GetUserByIdAsync(userId);
if (user == null)
{
- throw new InvalidOperationException("�û�������");
+ throw new InvalidOperationException("用户不存在");
}
try
{
- // ��ȡ�ͻ���IP������ʹ�ÿ��ַ�����Ϊռλ����ʵ��IPӦ��Controller���룩
+ // 获取客户端IP(这里使用空字符串作为占位,实际IP应由Controller传入)
var clientIp = deviceInfo ?? string.Empty;
var now = DateTime.Now;
- // 6.1 ��¼��¼��־
+ // 6.1 记录登录日志
var loginLog = new UserLoginLog
{
UserId = userId,
@@ -446,7 +457,7 @@ public class AuthService : IAuthService
await _dbContext.UserLoginLogs.AddAsync(loginLog);
- // �����û�����¼ʱ��
+ // 更新用户最后登录时间
user.LastLoginTime = now;
user.LastLoginIp = clientIp;
_dbContext.Users.Update(user);
@@ -455,7 +466,7 @@ public class AuthService : IAuthService
_logger.LogInformation("Login recorded: UserId={UserId}, Device={Device}, IP={IP}", userId, device, clientIp);
- // 6.4 �����û���uid���dzƺ�ͷ��
+ // 6.4 返回用户的uid、昵称和头像
return new RecordLoginResponse
{
Uid = user.Uid,
@@ -471,33 +482,33 @@ public class AuthService : IAuthService
}
///
- /// H5���ֻ��ţ�������֤�룩
+ /// H5绑定手机号(无需验证码)
/// Requirements: 13.1
///
public async Task BindMobileH5Async(long userId, string mobile)
{
if (string.IsNullOrWhiteSpace(mobile))
{
- throw new ArgumentException("�ֻ��Ų���Ϊ��", nameof(mobile));
+ throw new ArgumentException("手机号不能为空", nameof(mobile));
}
- // ��ȡ��ǰ�û�
+ // 获取当前用户
var currentUser = await _userService.GetUserByIdAsync(userId);
if (currentUser == null)
{
- throw new InvalidOperationException("�û�������");
+ throw new InvalidOperationException("用户不存在");
}
- // ����ֻ����Ƿ��ѱ������û���
+ // 检查手机号是否已被其他用户绑定
var existingUser = await _userService.GetUserByMobileAsync(mobile);
if (existingUser != null && existingUser.Id != userId)
{
- // �ֻ����ѱ������û�����Ҫ�ϲ��˻�
+ // 手机号已被其他用户绑定,需要合并账户
return await MergeAccountsAsync(currentUser, existingUser);
}
- // �ֻ���δ����ֱ�Ӹ��µ�ǰ�û����ֻ���
+ // 手机号未被绑定,直接更新当前用户的手机号
await _userService.UpdateUserAsync(userId, new UpdateUserDto { Mobile = mobile });
_logger.LogInformation("H5 Mobile bound successfully: UserId={UserId}, Mobile={Mobile}", userId, MaskMobile(mobile));
@@ -505,7 +516,7 @@ public class AuthService : IAuthService
}
///
- /// �˺�ע��
+ /// 账号注销
/// Requirements: 7.1-7.3
///
public async Task LogOffAsync(long userId, int type)
@@ -513,23 +524,23 @@ public class AuthService : IAuthService
var user = await _userService.GetUserByIdAsync(userId);
if (user == null)
{
- throw new InvalidOperationException("�û�������");
+ throw new InvalidOperationException("用户不存在");
}
try
{
- // 7.1 ��¼ע��������־
- var action = type == 0 ? "ע���˺�" : "ȡ��ע��";
+ // 7.1 记录注销操作日志
+ var action = type == 0 ? "注销账号" : "取消注销";
_logger.LogInformation("User log off request: UserId={UserId}, Type={Type}, Action={Action}", userId, type, action);
- // ����������Ӹ����ע���������磺
- // - ���û�״̬����Ϊ��ע��
- // - �����û���صĻ���
- // - ����֪ͨ��
+ // 这里可以添加更多的注销逻辑,比如:
+ // - 将用户状态设置为已注销
+ // - 清除用户相关的缓存
+ // - 发送通知等
if (type == 0)
{
- // ע���˺� - ���������û�״̬Ϊ����
+ // 注销账号 - 软删除,设置用户状态为禁用
user.Status = 0;
_dbContext.Users.Update(user);
await _dbContext.SaveChangesAsync();
@@ -537,14 +548,14 @@ public class AuthService : IAuthService
}
else if (type == 1)
{
- // ȡ��ע�� - �ָ��û�״̬
+ // 取消注销 - 恢复用户状态
user.Status = 1;
_dbContext.Users.Update(user);
await _dbContext.SaveChangesAsync();
_logger.LogInformation("User account reactivated: UserId={UserId}", userId);
}
- // 7.2 ����ע���ɹ�����Ϣ��ͨ�����׳��쳣����ʾ�ɹ���
+ // 7.2 返回注销成功的信息(通过不抛出异常来表示成功)
}
catch (Exception ex)
{
@@ -557,24 +568,24 @@ public class AuthService : IAuthService
#region Refresh Token Methods
///
- /// ���� Refresh Token ���洢�����ݿ�
+ /// 生成 Refresh Token 并存储到数据库
/// Requirements: 1.4, 1.5, 4.1
///
- /// �û�ID
- /// �ͻ��� IP ��ַ
- /// ���ɵ� Refresh Token ����
+ /// 用户ID
+ /// 客户端 IP 地址
+ /// 生成的 Refresh Token 字符串
private async Task GenerateRefreshTokenAsync(long userId, string? ipAddress)
{
- // ������� Refresh Token
+ // 生成随机 Refresh Token
var refreshToken = GenerateSecureRandomString(RefreshTokenLength);
- // ���� SHA256 ��ϣֵ���ڴ洢
+ // 计算 SHA256 哈希值用于存储
var tokenHash = ComputeSha256Hash(refreshToken);
- // �������ʱ�䣨7�죩
+ // 设置过期时间(7天)
var expiresAt = DateTime.Now.AddDays(_jwtSettings.RefreshTokenExpirationDays);
- // �������ݿ��¼
+ // 保存数据库记录
var userRefreshToken = new UserRefreshToken
{
UserId = userId,
@@ -593,21 +604,21 @@ public class AuthService : IAuthService
}
///
- /// ���ɵ�¼��Ӧ������˫ Token��
+ /// 生成登录响应(包含双 Token)
/// Requirements: 1.1, 1.2, 1.3, 1.4, 1.5
///
- /// �û�ʵ��
- /// �ͻ��� IP ��ַ
- /// ��¼��Ӧ
+ /// 用户实体
+ /// 客户端 IP 地址
+ /// 登录响应
private async Task GenerateLoginResponseAsync(User user, string? ipAddress)
{
- // ���� Access Token (JWT)
+ // 生成 Access Token (JWT)
var accessToken = _jwtService.GenerateToken(user);
- // ���� Refresh Token ���洢
+ // 生成 Refresh Token 并存储
var refreshToken = await GenerateRefreshTokenAsync(user.Id, ipAddress);
- // ���� Access Token ����ʱ�䣨�룩
+ // 计算 Access Token 过期时间(秒)
var expiresIn = _jwtSettings.ExpirationMinutes * 60;
return new LoginResponse
@@ -620,7 +631,7 @@ public class AuthService : IAuthService
}
///
- /// ˢ�� Token
+ /// 刷新 Token
/// Requirements: 2.1-2.6
///
public async Task RefreshTokenAsync(string refreshToken, string? ipAddress)
@@ -628,15 +639,15 @@ public class AuthService : IAuthService
if (string.IsNullOrWhiteSpace(refreshToken))
{
_logger.LogWarning("Refresh token is empty");
- return RefreshTokenResult.Fail("ˢ�����Ʋ���Ϊ��");
+ return RefreshTokenResult.Fail("刷新令牌不能为空");
}
try
{
- // ���� Token ��ϣֵ
+ // 计算 Token 哈希值
var tokenHash = ComputeSha256Hash(refreshToken);
- // ���� Token ��¼
+ // 查找 Token 记录
var storedToken = await _dbContext.UserRefreshTokens
.Include(t => t.User)
.FirstOrDefaultAsync(t => t.TokenHash == tokenHash);
@@ -644,47 +655,47 @@ public class AuthService : IAuthService
if (storedToken == null)
{
_logger.LogWarning("Refresh token not found: {TokenHash}", tokenHash.Substring(0, 8) + "...");
- return RefreshTokenResult.Fail("��Ч��ˢ������");
+ return RefreshTokenResult.Fail("无效的刷新令牌");
}
- // ����Ƿ��ѹ���
+ // 检查是否已过期
if (storedToken.IsExpired)
{
_logger.LogWarning("Refresh token expired for user {UserId}", storedToken.UserId);
- return RefreshTokenResult.Fail("ˢ�������ѹ���");
+ return RefreshTokenResult.Fail("刷新令牌已过期");
}
- // ����Ƿ��ѳ���
+ // 检查是否已撤销
if (storedToken.IsRevoked)
{
_logger.LogWarning("Refresh token revoked for user {UserId}", storedToken.UserId);
- return RefreshTokenResult.Fail("ˢ��������ʧЧ");
+ return RefreshTokenResult.Fail("刷新令牌已失效");
}
- // ����û��Ƿ��������Ч
+ // 检查用户是否存在且有效
var user = storedToken.User;
if (user == null)
{
_logger.LogWarning("User not found for refresh token");
- return RefreshTokenResult.Fail("�û�������");
+ return RefreshTokenResult.Fail("用户不存在");
}
if (user.Status == 0)
{
_logger.LogWarning("User {UserId} is disabled", user.Id);
- return RefreshTokenResult.Fail("�˺��ѱ�����");
+ return RefreshTokenResult.Fail("账号已被禁用");
}
- // Token �ֻ��������µ� Refresh Token
+ // Token 轮换:生成新的 Refresh Token
var newRefreshToken = GenerateSecureRandomString(RefreshTokenLength);
var newTokenHash = ComputeSha256Hash(newRefreshToken);
- // ������ Token ����¼������ϵ
+ // 标记旧 Token 的记录和替换关系
storedToken.RevokedAt = DateTime.Now;
storedToken.RevokedByIp = ipAddress;
storedToken.ReplacedByToken = newTokenHash;
- // �����µ� Token ��¼
+ // 保存新的 Token 记录
var newUserRefreshToken = new UserRefreshToken
{
UserId = user.Id,
@@ -697,7 +708,7 @@ public class AuthService : IAuthService
await _dbContext.UserRefreshTokens.AddAsync(newUserRefreshToken);
await _dbContext.SaveChangesAsync();
- // �����µ� Access Token
+ // 生成新的 Access Token
var accessToken = _jwtService.GenerateToken(user);
var expiresIn = _jwtSettings.ExpirationMinutes * 60;
@@ -714,12 +725,12 @@ public class AuthService : IAuthService
catch (Exception ex)
{
_logger.LogError(ex, "Error refreshing token");
- return RefreshTokenResult.Fail("ˢ������ʧ�ܣ����Ժ�����");
+ return RefreshTokenResult.Fail("刷新令牌失败,请稍后重试");
}
}
///
- /// ���� Token
+ /// 撤销 Token
/// Requirements: 4.4
///
public async Task RevokeTokenAsync(string refreshToken, string? ipAddress)
@@ -732,10 +743,10 @@ public class AuthService : IAuthService
try
{
- // ���� Token ��ϣֵ
+ // 计算 Token 哈希值
var tokenHash = ComputeSha256Hash(refreshToken);
- // ���� Token ��¼
+ // 查找 Token 记录
var storedToken = await _dbContext.UserRefreshTokens
.FirstOrDefaultAsync(t => t.TokenHash == tokenHash);
@@ -745,14 +756,14 @@ public class AuthService : IAuthService
return;
}
- // ����Ѿ�������ֱ�ӷ���
+ // 如果已经撤销,直接返回
if (storedToken.IsRevoked)
{
_logger.LogInformation("Refresh token already revoked");
return;
}
- // ���� Token
+ // 撤销 Token
storedToken.RevokedAt = DateTime.Now;
storedToken.RevokedByIp = ipAddress;
@@ -768,14 +779,14 @@ public class AuthService : IAuthService
}
///
- /// �����û������� Token
+ /// 撤销用户所有的 Token
/// Requirements: 4.4
///
public async Task RevokeAllUserTokensAsync(long userId, string? ipAddress)
{
try
{
- // �����û�������Ч�� Token
+ // 查找用户所有有效的 Token
var activeTokens = await _dbContext.UserRefreshTokens
.Where(t => t.UserId == userId && t.RevokedAt == null)
.ToListAsync();
@@ -809,7 +820,7 @@ public class AuthService : IAuthService
#region Private Helper Methods
///
- /// �ϲ��˻� - ����ǰ�û���openidǨ�Ƶ��ֻ����û�
+ /// 合并账户 - 将当前用户的openid迁移到手机号用户
///
private async Task MergeAccountsAsync(User currentUser, User mobileUser)
{
@@ -819,7 +830,7 @@ public class AuthService : IAuthService
_logger.LogInformation("Merging accounts: CurrentUserId={CurrentUserId}, MobileUserId={MobileUserId}",
currentUser.Id, mobileUser.Id);
- // 5.2 ����ǰ�û���openidǨ�Ƶ��ֻ����û�
+ // 5.2 将当前用户的openid迁移到手机号用户
if (!string.IsNullOrWhiteSpace(currentUser.OpenId))
{
mobileUser.OpenId = currentUser.OpenId;
@@ -831,13 +842,13 @@ public class AuthService : IAuthService
mobileUser.UpdateTime = DateTime.Now;
_dbContext.Users.Update(mobileUser);
- // ɾ����ǰ�û�
+ // 删除当前用户
_dbContext.Users.Remove(currentUser);
await _dbContext.SaveChangesAsync();
await transaction.CommitAsync();
- // 5.3 �����µ�token
+ // 5.3 生成新的token
var newToken = _jwtService.GenerateToken(mobileUser);
_logger.LogInformation("Accounts merged successfully: NewUserId={NewUserId}", mobileUser.Id);
@@ -906,18 +917,18 @@ public class AuthService : IAuthService
}
///
- /// ����Ĭ��ͷ��URL
+ /// 生成默认头像URL
///
private static string GenerateDefaultAvatar(string seed)
{
- // ʹ����������һ����Ĭ��ͷ��URL
- // ʵ����Ŀ�п���ʹ��Identicon�������ͷ�����ɷ���
+ // 使用随机数生成一个简单的默认头像URL
+ // 实际项目中可以使用Identicon或其他头像生成方案
var hash = ComputeMd5(seed);
return $"https://api.dicebear.com/7.x/identicon/svg?seed={hash}";
}
///
- /// ����MD5��ϣ
+ /// 计算MD5哈希
///
private static string ComputeMd5(string input)
{
@@ -927,7 +938,7 @@ public class AuthService : IAuthService
}
///
- /// ��������ַ���
+ /// 生成随机字符串
///
private static string GenerateRandomString(int length)
{
@@ -941,7 +952,7 @@ public class AuthService : IAuthService
}
///
- /// �����ֻ���
+ /// 手机号脱敏
///
private static string MaskMobile(string mobile)
{
@@ -952,7 +963,7 @@ public class AuthService : IAuthService
}
///
- /// ��ȡ����е�����
+ /// 获取年份中的周数
///
private static int GetWeekOfYear(DateTime date)
{
@@ -961,7 +972,7 @@ public class AuthService : IAuthService
}
///
- /// ���� SHA256 ��ϣֵ
+ /// 计算 SHA256 哈希值
/// Requirements: 4.1
///
private static string ComputeSha256Hash(string input)
@@ -972,7 +983,7 @@ public class AuthService : IAuthService
}
///
- /// ���ɰ�ȫ������ַ��������� Refresh Token��
+ /// 生成安全随机字符串(用于 Refresh Token)
///
private static string GenerateSecureRandomString(int length)
{