新增顶号后,强制下线功能

新增进房间第一个人全员看ta
This commit is contained in:
youngq 2024-08-13 15:23:36 +08:00
parent 09fbfae8b4
commit 03358fc745
7 changed files with 110 additions and 11 deletions

View File

@ -1,12 +1,14 @@
using Masuit.Tools; using Masuit.Tools;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using NetTaste; using NetTaste;
using SqlSugar; using SqlSugar;
using System.Configuration; using System.Configuration;
using System.Security.Claims; using System.Security.Claims;
using WGShare.API.Controllers.Basic; using WGShare.API.Controllers.Basic;
using WGShare.API.Helpers; using WGShare.API.Helpers;
using WGShare.API.Hubs;
using WGShare.Domain.Constant; using WGShare.Domain.Constant;
using WGShare.Domain.DTOs.Login; using WGShare.Domain.DTOs.Login;
using WGShare.Domain.Entities; using WGShare.Domain.Entities;
@ -22,13 +24,16 @@ namespace WGShare.API.Controllers
private readonly ISqlSugarClient _sqlSugar; private readonly ISqlSugarClient _sqlSugar;
private readonly JwtHelper _jwtHelper; private readonly JwtHelper _jwtHelper;
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private readonly IHubContext<SessionManageHub, IMessageClient> _hubContext;
public AuthController(ISqlSugarClient sqlSugar, JwtHelper jwtHelper, public AuthController(ISqlSugarClient sqlSugar, JwtHelper jwtHelper,
IConfiguration configuration) IConfiguration configuration,
IHubContext<SessionManageHub, IMessageClient> hubContext)
{ {
_sqlSugar = sqlSugar; _sqlSugar = sqlSugar;
_jwtHelper = jwtHelper; _jwtHelper = jwtHelper;
this._configuration = configuration; this._configuration = configuration;
this._hubContext = hubContext;
} }
/// <summary> /// <summary>
@ -84,13 +89,31 @@ namespace WGShare.API.Controllers
btnAutn.Add(new Claim("uname", user.UserName)); btnAutn.Add(new Claim("uname", user.UserName));
btnAutn.Add(new Claim("ssid", user.ScreenShareId)); btnAutn.Add(new Claim("ssid", user.ScreenShareId));
// 强制下线
var connectId = RedisHelper.Instance.HGet(RedisKeyConstant.SessionManage.GetOnlineUserKey(user.TenantId), user.Id);
if (!string.IsNullOrWhiteSpace(connectId))
{
await _hubContext.Clients.Client(connectId).ForceLogout("账号已在其他地方登录,您被迫下线!");
}
var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn);
var refreshToken = Guid.NewGuid().ToString(); var refreshToken = Guid.NewGuid().ToString();
RedisHelper.Instance.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken), user, TimeSpan.FromDays(30).TotalSeconds.ToInt32()); using (var pipe = RedisHelper.Instance.StartPipe())
{
// 设置刷新token
pipe.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken), user, TimeSpan.FromDays(7).TotalSeconds.ToInt32());
// 记录accessToken
pipe.Set(RedisKeyConstant.Data.GetAccessTokenKey(user.Id), accessToken, _configuration["Jwt:Expires"].ToInt32());
pipe.EndPipe();
}
return Ok(new return Ok(new
{ {
perms = user.PermValue, perms = user.PermValue,
token = _jwtHelper.CreateToken(user.Id, btnAutn), token = accessToken,
refresh_token = refreshToken, refresh_token = refreshToken,
roleId = user.RoleId, roleId = user.RoleId,
userName = user.UserName, userName = user.UserName,
@ -124,10 +147,16 @@ namespace WGShare.API.Controllers
btnAutn.Add(new Claim("uname", user.UserName)); btnAutn.Add(new Claim("uname", user.UserName));
btnAutn.Add(new Claim("ssid", user.ScreenShareId)); btnAutn.Add(new Claim("ssid", user.ScreenShareId));
var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn);
var refreshTokenNew = Guid.NewGuid().ToString(); var refreshTokenNew = Guid.NewGuid().ToString();
RedisHelper.Instance.Del(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken)); using (var pipe = RedisHelper.Instance.StartPipe())
RedisHelper.Instance.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshTokenNew), user, TimeSpan.FromDays(30).TotalSeconds.ToInt32()); {
pipe.Del(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken));
pipe.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshTokenNew), user, TimeSpan.FromDays(7).TotalSeconds.ToInt32());
pipe.Set(RedisKeyConstant.Data.GetAccessTokenKey(user.Id), accessToken, _configuration["Jwt:Expires"].ToInt32());
pipe.EndPipe();
}
return Ok(new return Ok(new
{ {

View File

@ -82,7 +82,6 @@ namespace WGShare.API.Controllers.Frontend
.SplitInsert(x => !x.Any()) .SplitInsert(x => !x.Any())
.ToStorage().AsInsertable.ExecuteCommandAsync(); .ToStorage().AsInsertable.ExecuteCommandAsync();
//await _sqlSugar.Insertable(entities).ExecuteCommandAsync();
RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, inputDTO.RoomNum), inputDTO.UserId, user); RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, inputDTO.RoomNum), inputDTO.UserId, user);
await _hubContext.Clients.Group(inputDTO.RoomNum).ManagerRefresh(user); await _hubContext.Clients.Group(inputDTO.RoomNum).ManagerRefresh(user);
@ -258,7 +257,7 @@ namespace WGShare.API.Controllers.Frontend
}); });
RedisHelper.Instance.HMSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), allUsers); RedisHelper.Instance.HMSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), allUsers);
// 通知其他人 // 通知其他人
await _hubContext.Clients.GroupExcept(roomNum, allUsers[UId].ConnectId).OperAllMicr(enableMicr); await _hubContext.Clients.Group(roomNum).OperAllMicr(enableMicr);
} }
@ -368,7 +367,7 @@ namespace WGShare.API.Controllers.Frontend
[HttpGet("join")] [HttpGet("join")]
public async Task JoinChannel([FromQuery] string roomNum, [FromQuery] bool enableMicr = false, [FromQuery] bool enableCamera = false) public async Task JoinChannel([FromQuery] string roomNum, [FromQuery] bool enableMicr = false, [FromQuery] bool enableCamera = false)
{ {
var isManager = await _sqlSugar.Queryable<RoomManager>() var isRoomManager = await _sqlSugar.Queryable<RoomManager>()
.InnerJoin<Room>((rm, r) => r.Id == rm.RoomId) .InnerJoin<Room>((rm, r) => r.Id == rm.RoomId)
.Where((rm, r) => r.RoomNum == roomNum && rm.UserId == UId) .Where((rm, r) => r.RoomNum == roomNum && rm.UserId == UId)
.AnyAsync(); .AnyAsync();
@ -384,10 +383,15 @@ namespace WGShare.API.Controllers.Frontend
ScreenShareId = ScreenShareId, ScreenShareId = ScreenShareId,
RoleId = RoleId, RoleId = RoleId,
RoleName = ((RoleEnums)RoleId.ToInt32()).GetDescription(), RoleName = ((RoleEnums)RoleId.ToInt32()).GetDescription(),
IsRoomManager = isManager IsRoomManager = isRoomManager
}; };
using (var pipe = RedisHelper.Instance.StartPipe()) using (var pipe = RedisHelper.Instance.StartPipe())
{ {
var script = $@"local exists = redis.call('HLEN', KEYS[1])
if exists == 0 then redis.call('HSET', KEYS[2], ARGV[1], ARGV[2]) end
return exists";
pipe.Eval(script, [RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), RedisKeyConstant.SessionManage.GetChannelShowUserKey(TenantId)], roomNum, UId);
pipe.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), UId, userInfo.ToJsonString()); pipe.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, roomNum), UId, userInfo.ToJsonString());
pipe.HSet(RedisKeyConstant.SessionManage.GetUserJoinChannelKey(UId), roomNum, 1); pipe.HSet(RedisKeyConstant.SessionManage.GetUserJoinChannelKey(UId), roomNum, 1);
pipe.EndPipe(); pipe.EndPipe();

View File

@ -97,5 +97,11 @@ namespace WGShare.API.Hubs
/// <param name="user"></param> /// <param name="user"></param>
/// <returns></returns> /// <returns></returns>
Task ManagerRefresh(ChannelUserInfo user); Task ManagerRefresh(ChannelUserInfo user);
/// <summary>
/// 强制退出
/// </summary>
/// <returns></returns>
Task ForceLogout(string msg);
} }
} }

View File

@ -28,7 +28,9 @@ namespace WGShare.API
Serialize = (x) => x.ToJsonString(), Serialize = (x) => x.ToJsonString(),
Deserialize = (x, t) => JsonConvert.DeserializeObject(x, t), Deserialize = (x, t) => JsonConvert.DeserializeObject(x, t),
}); });
#if !DEBUG
ResetRedisKey(); ResetRedisKey();
#endif
builder.Services.Configure<FormOptions>(options => builder.Services.Configure<FormOptions>(options =>
{ {
@ -43,6 +45,7 @@ namespace WGShare.API
options.Filters.Add<GlobalExceptionFilter>(); options.Filters.Add<GlobalExceptionFilter>();
// 全局模型赋值默认值 和 统一返回格式处理 // 全局模型赋值默认值 和 统一返回格式处理
options.Filters.Add<ModelActionFilter>(); options.Filters.Add<ModelActionFilter>();
options.Filters.Add<AuthonizationFilter>();
}).AddNewtonsoftJson(options => }).AddNewtonsoftJson(options =>
{ {
//修改属性名称的序列化方式,首字母小写,即驼峰样式 //修改属性名称的序列化方式,首字母小写,即驼峰样式

View File

@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.SignalR;
using WGShare.API.Helpers;
using WGShare.API.Hubs;
using WGShare.Domain.Constant;
using WGShare.Domain.Entities;
namespace WGShare.API.ServiceConfigs
{
public class AuthonizationFilter : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
//Console.WriteLine("验证结果:" + context.HttpContext.User.Identity.IsAuthenticated);
if (context.HttpContext.User.Identity.IsAuthenticated)
{
//context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult(new { message = "请先登录" });
var uid = context.HttpContext.User.Claims.FirstOrDefault(x => x.Type == "uid")?.Value;
if (string.IsNullOrWhiteSpace(uid))
{
context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult(new { message = "身份认证有误,请重新登录!" });
context.HttpContext.Response.StatusCode = 401;
return;
}
var cacheToken = RedisHelper.Instance.Get(RedisKeyConstant.Data.GetAccessTokenKey(uid));
if (string.IsNullOrWhiteSpace(cacheToken))
{
context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult(new { message = "身份失效,请重新登录!" });
context.HttpContext.Response.StatusCode = 401;
return;
}
var token = context.HttpContext.Request.Headers.Authorization.FirstOrDefault().Replace("Bearer ", "");
if (token != cacheToken)
{
context.Result = new Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult(new { message = "此账号已在别处登录,您被迫下线!" });
context.HttpContext.Response.StatusCode = 401;
return;
}
}
}
}
}

View File

@ -445,6 +445,12 @@
<param name="user"></param> <param name="user"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:WGShare.API.Hubs.IMessageClient.ForceLogout">
<summary>
强制退出
</summary>
<returns></returns>
</member>
<member name="M:WGShare.API.Hubs.SessionManageHub.JoinChannel(System.String,System.Boolean,System.Boolean)"> <member name="M:WGShare.API.Hubs.SessionManageHub.JoinChannel(System.String,System.Boolean,System.Boolean)">
<summary> <summary>
加入频道 加入频道

View File

@ -57,9 +57,16 @@ namespace WGShare.Domain.Constant
/// </summary> /// </summary>
/// <param name="refreshToken"></param> /// <param name="refreshToken"></param>
/// <returns></returns> /// <returns></returns>
public static string GetRefreshTokenKey(string refreshToken) => $@"data:refresh:{refreshToken}"; public static string GetRefreshTokenKey(string refreshToken) => $@"data:refresh_tk:{refreshToken}";
public static string GetScreenShareIdKey => $@"data:screen_share_id"; public static string GetScreenShareIdKey => $@"data:screen_share_id";
/// <summary>
/// 获取Accesstoken Redis Key
/// </summary>
/// <param name="uid"></param>
/// <returns></returns>
public static string GetAccessTokenKey(string uid) => $@"data:access_tk:{uid}";
} }