开启单设备登陆情况下,单用户可以在PC、APP端同时登陆连接signlar,不被强制下线并可以接收消息
This commit is contained in:
parent
97043f00fd
commit
4368c5510f
@ -99,7 +99,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
// 登录成功则清空密码错误次数
|
// 登录成功则清空密码错误次数
|
||||||
_sysCacheService.Remove(keyPasswordErrorTimes);
|
_sysCacheService.Remove(keyPasswordErrorTimes);
|
||||||
|
|
||||||
return await CreateToken(user);
|
return await CreateToken(user, input.LoginMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -148,19 +148,23 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
|
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
|
||||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||||
|
|
||||||
return await CreateToken(user);
|
return await CreateToken(user, input.LoginMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成Token令牌 🔖
|
/// 生成Token令牌 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
|
/// <param name="loginMode"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public virtual async Task<LoginOutput> CreateToken(SysUser user)
|
public virtual async Task<LoginOutput> CreateToken(SysUser user, LoginModeEnum loginMode)
|
||||||
{
|
{
|
||||||
|
// 兼容处理前端未传递loginMode,导致收不到消息
|
||||||
|
if (loginMode == 0) loginMode = LoginModeEnum.PC;
|
||||||
|
|
||||||
// 单用户登录
|
// 单用户登录
|
||||||
await _sysOnlineUserService.SingleLogin(user.Id);
|
await _sysOnlineUserService.SingleLogin(user.Id, loginMode);
|
||||||
|
|
||||||
// 生成Token令牌
|
// 生成Token令牌
|
||||||
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
||||||
@ -174,6 +178,7 @@ public class AppAuthService : IDynamicApiController, ITransient
|
|||||||
{ AppClaimConst.OrgId, user.OrgId },
|
{ AppClaimConst.OrgId, user.OrgId },
|
||||||
{ AppClaimConst.OrgName, user.SysOrg?.Name },
|
{ AppClaimConst.OrgName, user.SysOrg?.Name },
|
||||||
{ AppClaimConst.OrgType, user.SysOrg?.Type },
|
{ AppClaimConst.OrgType, user.SysOrg?.Type },
|
||||||
|
{ ClaimConst.LoginMode, loginMode },
|
||||||
}, tokenExpire);
|
}, tokenExpire);
|
||||||
|
|
||||||
// 生成刷新Token令牌
|
// 生成刷新Token令牌
|
||||||
|
|||||||
@ -65,4 +65,10 @@ public partial class SysOnlineUser : EntityTenantId
|
|||||||
[SugarColumn(ColumnDescription = "操作系统", Length = 128)]
|
[SugarColumn(ColumnDescription = "操作系统", Length = 128)]
|
||||||
[MaxLength(128)]
|
[MaxLength(128)]
|
||||||
public string? Os { get; set; }
|
public string? Os { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登陆模式
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnDescription = "登陆模式")]
|
||||||
|
public LoginModeEnum LoginMode { get; set; }
|
||||||
}
|
}
|
||||||
@ -47,6 +47,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
|||||||
var account = httpContext.User.FindFirst(ClaimConst.Account)?.Value;
|
var account = httpContext.User.FindFirst(ClaimConst.Account)?.Value;
|
||||||
var realName = httpContext.User.FindFirst(ClaimConst.RealName)?.Value;
|
var realName = httpContext.User.FindFirst(ClaimConst.RealName)?.Value;
|
||||||
var tenantId = (httpContext.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong();
|
var tenantId = (httpContext.User.FindFirst(ClaimConst.TenantId)?.Value).ToLong();
|
||||||
|
var loginMode = (LoginModeEnum)(httpContext.User.FindFirst(ClaimConst.LoginMode)?.Value).ToInt();
|
||||||
|
|
||||||
var user = new SysOnlineUser
|
var user = new SysOnlineUser
|
||||||
{
|
{
|
||||||
@ -59,13 +60,14 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
|
|||||||
Browser = httpContext.GetClientBrowser(),
|
Browser = httpContext.GetClientBrowser(),
|
||||||
Os = httpContext.GetClientOs(),
|
Os = httpContext.GetClientOs(),
|
||||||
TenantId = tenantId,
|
TenantId = tenantId,
|
||||||
|
LoginMode = loginMode,
|
||||||
};
|
};
|
||||||
await _sysOnlineUerRep.InsertAsync(user);
|
await _sysOnlineUerRep.InsertAsync(user);
|
||||||
|
|
||||||
// 是否开启单用户登录
|
// 是否开启单用户登录
|
||||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||||
{
|
{
|
||||||
_sysCacheService.Set(CacheConst.KeyUserOnline + user.UserId, user);
|
_sysCacheService.Set(CacheConst.KeyUserOnline + user.UserId + loginMode, user);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -34,6 +34,11 @@ public class LoginInput
|
|||||||
/// 验证码
|
/// 验证码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Code { get; set; }
|
public string Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登陆模式
|
||||||
|
/// </summary>
|
||||||
|
public LoginModeEnum LoginMode { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoginPhoneInput
|
public class LoginPhoneInput
|
||||||
@ -52,4 +57,9 @@ public class LoginPhoneInput
|
|||||||
/// <example>123456</example>
|
/// <example>123456</example>
|
||||||
[Required(ErrorMessage = "验证码不能为空"), MinLength(4, ErrorMessage = "验证码不能少于4个字符")]
|
[Required(ErrorMessage = "验证码不能为空"), MinLength(4, ErrorMessage = "验证码不能少于4个字符")]
|
||||||
public string Code { get; set; }
|
public string Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 登陆模式
|
||||||
|
/// </summary>
|
||||||
|
public LoginModeEnum LoginMode { get; set; }
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
|||||||
// 登录成功则清空密码错误次数
|
// 登录成功则清空密码错误次数
|
||||||
_sysCacheService.Remove(keyPasswordErrorTimes);
|
_sysCacheService.Remove(keyPasswordErrorTimes);
|
||||||
|
|
||||||
return await CreateToken(user);
|
return await CreateToken(user, input.LoginMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -202,19 +202,23 @@ public class SysAuthService : IDynamicApiController, ITransient
|
|||||||
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
|
var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter().FirstAsync(u => u.Phone.Equals(input.Phone));
|
||||||
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
_ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
|
||||||
|
|
||||||
return await CreateToken(user);
|
return await CreateToken(user, input.LoginMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成Token令牌 🔖
|
/// 生成Token令牌 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
|
/// <param name="loginMode"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
internal async Task<LoginOutput> CreateToken(SysUser user)
|
internal async Task<LoginOutput> CreateToken(SysUser user, LoginModeEnum loginMode)
|
||||||
{
|
{
|
||||||
|
// 兼容处理前端未传递loginMode,导致收不到消息
|
||||||
|
if (loginMode == 0) loginMode = LoginModeEnum.PC;
|
||||||
|
|
||||||
// 单用户登录
|
// 单用户登录
|
||||||
await _sysOnlineUserService.SingleLogin(user.Id);
|
await _sysOnlineUserService.SingleLogin(user.Id, loginMode);
|
||||||
|
|
||||||
// 生成Token令牌
|
// 生成Token令牌
|
||||||
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
var tokenExpire = await _sysConfigService.GetTokenExpire();
|
||||||
@ -228,6 +232,7 @@ public class SysAuthService : IDynamicApiController, ITransient
|
|||||||
{ ClaimConst.OrgId, user.OrgId },
|
{ ClaimConst.OrgId, user.OrgId },
|
||||||
{ ClaimConst.OrgName, user.SysOrg?.Name },
|
{ ClaimConst.OrgName, user.SysOrg?.Name },
|
||||||
{ ClaimConst.OrgType, user.SysOrg?.Type },
|
{ ClaimConst.OrgType, user.SysOrg?.Type },
|
||||||
|
{ ClaimConst.LoginMode, loginMode },
|
||||||
}, tokenExpire);
|
}, tokenExpire);
|
||||||
|
|
||||||
// 生成刷新Token令牌
|
// 生成刷新Token令牌
|
||||||
|
|||||||
@ -50,9 +50,14 @@ public class SysMessageService : IDynamicApiController, ITransient
|
|||||||
// 是否开启单用户登录
|
// 是否开启单用户登录
|
||||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||||
{
|
{
|
||||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
var values = Enum.GetValues(typeof(LoginModeEnum)).Cast<LoginModeEnum>().ToList();
|
||||||
if (user == null) return;
|
|
||||||
await _chatHubContext.Clients.AllExcept(user.ConnectionId).ReceiveMessage(input);
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey + value);
|
||||||
|
if (user == null) continue;
|
||||||
|
await _chatHubContext.Clients.AllExcept(user.ConnectionId).ReceiveMessage(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -78,9 +83,14 @@ public class SysMessageService : IDynamicApiController, ITransient
|
|||||||
// 是否开启单用户登录
|
// 是否开启单用户登录
|
||||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||||
{
|
{
|
||||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
var values = Enum.GetValues(typeof(LoginModeEnum)).Cast<LoginModeEnum>().ToList();
|
||||||
if (user == null) return;
|
|
||||||
await _chatHubContext.Clients.Client(user.ConnectionId).ReceiveMessage(input);
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey + value);
|
||||||
|
if (user == null) continue;
|
||||||
|
await _chatHubContext.Clients.Client(user.ConnectionId).ReceiveMessage(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -109,8 +119,13 @@ public class SysMessageService : IDynamicApiController, ITransient
|
|||||||
// 是否开启单用户登录
|
// 是否开启单用户登录
|
||||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||||
{
|
{
|
||||||
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey);
|
var values = Enum.GetValues(typeof(LoginModeEnum)).Cast<LoginModeEnum>().ToList();
|
||||||
if (user != null) userList.Add(user.ConnectionId);
|
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
var user = _sysCacheService.Get<SysOnlineUser>(cacheKey + value);
|
||||||
|
if (user != null) userList.Add(user.ConnectionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -109,8 +109,8 @@ public class SysOAuthService : IDynamicApiController, ITransient
|
|||||||
wechatUser = await _sysOAuthUserRep.AsQueryable().Includes(u => u.SysUser).ClearFilter().FirstAsync(u => u.OpenId == openIdClaim.Value);
|
wechatUser = await _sysOAuthUserRep.AsQueryable().Includes(u => u.SysUser).ClearFilter().FirstAsync(u => u.OpenId == openIdClaim.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建Token令牌
|
// 构建Token令牌 TODO 这里先默认所有回调登陆的都是PC
|
||||||
var token = await App.GetRequiredService<SysAuthService>().CreateToken(wechatUser.SysUser);
|
var token = await App.GetRequiredService<SysAuthService>().CreateToken(wechatUser.SysUser, LoginModeEnum.PC);
|
||||||
|
|
||||||
return new RedirectResult($"{redirectUrl}/#/login?token={token.AccessToken}");
|
return new RedirectResult($"{redirectUrl}/#/login?token={token.AccessToken}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,16 +74,21 @@ public class SysOnlineUserService : IDynamicApiController, ITransient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 单用户登录
|
/// 单用户登录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="loginMode"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[NonAction]
|
[NonAction]
|
||||||
public async Task SingleLogin(long userId)
|
public async Task SingleLogin(long userId, LoginModeEnum loginMode)
|
||||||
{
|
{
|
||||||
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysSingleLogin))
|
||||||
{
|
{
|
||||||
var users = await _sysOnlineUerRep.GetListAsync(u => u.UserId == userId);
|
var users = await _sysOnlineUerRep.GetListAsync(u => u.UserId == userId);
|
||||||
foreach (var user in users)
|
foreach (var user in users)
|
||||||
{
|
{
|
||||||
await ForceOffline(user);
|
if (loginMode == user.LoginMode)
|
||||||
|
{
|
||||||
|
await ForceOffline(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user