diff --git a/WGShare.API/Controllers/AuthController.cs b/WGShare.API/Controllers/AuthController.cs index a3eb4ab..ea0c581 100644 --- a/WGShare.API/Controllers/AuthController.cs +++ b/WGShare.API/Controllers/AuthController.cs @@ -1,12 +1,14 @@ using Masuit.Tools; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; using NetTaste; using SqlSugar; using System.Configuration; using System.Security.Claims; using WGShare.API.Controllers.Basic; using WGShare.API.Helpers; +using WGShare.API.Hubs; using WGShare.Domain.Constant; using WGShare.Domain.DTOs.Login; using WGShare.Domain.Entities; @@ -22,13 +24,16 @@ namespace WGShare.API.Controllers private readonly ISqlSugarClient _sqlSugar; private readonly JwtHelper _jwtHelper; private readonly IConfiguration _configuration; + private readonly IHubContext _hubContext; public AuthController(ISqlSugarClient sqlSugar, JwtHelper jwtHelper, - IConfiguration configuration) + IConfiguration configuration, + IHubContext hubContext) { _sqlSugar = sqlSugar; _jwtHelper = jwtHelper; this._configuration = configuration; + this._hubContext = hubContext; } /// @@ -84,13 +89,31 @@ namespace WGShare.API.Controllers btnAutn.Add(new Claim("uname", user.UserName)); 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(); - 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 { perms = user.PermValue, - token = _jwtHelper.CreateToken(user.Id, btnAutn), + token = accessToken, refresh_token = refreshToken, roleId = user.RoleId, userName = user.UserName, @@ -124,10 +147,16 @@ namespace WGShare.API.Controllers btnAutn.Add(new Claim("uname", user.UserName)); btnAutn.Add(new Claim("ssid", user.ScreenShareId)); - + var accessToken = _jwtHelper.CreateToken(user.Id, btnAutn); var refreshTokenNew = Guid.NewGuid().ToString(); - RedisHelper.Instance.Del(RedisKeyConstant.Data.GetRefreshTokenKey(refreshToken)); - RedisHelper.Instance.Set(RedisKeyConstant.Data.GetRefreshTokenKey(refreshTokenNew), user, TimeSpan.FromDays(30).TotalSeconds.ToInt32()); + using (var pipe = RedisHelper.Instance.StartPipe()) + { + 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 { diff --git a/WGShare.API/Controllers/Frontend/RoomController.cs b/WGShare.API/Controllers/Frontend/RoomController.cs index a56ddf7..3f7e788 100644 --- a/WGShare.API/Controllers/Frontend/RoomController.cs +++ b/WGShare.API/Controllers/Frontend/RoomController.cs @@ -82,7 +82,6 @@ namespace WGShare.API.Controllers.Frontend .SplitInsert(x => !x.Any()) .ToStorage().AsInsertable.ExecuteCommandAsync(); - //await _sqlSugar.Insertable(entities).ExecuteCommandAsync(); RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, inputDTO.RoomNum), inputDTO.UserId, 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); // 通知其他人 - 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")] public async Task JoinChannel([FromQuery] string roomNum, [FromQuery] bool enableMicr = false, [FromQuery] bool enableCamera = false) { - var isManager = await _sqlSugar.Queryable() + var isRoomManager = await _sqlSugar.Queryable() .InnerJoin((rm, r) => r.Id == rm.RoomId) .Where((rm, r) => r.RoomNum == roomNum && rm.UserId == UId) .AnyAsync(); @@ -384,10 +383,15 @@ namespace WGShare.API.Controllers.Frontend ScreenShareId = ScreenShareId, RoleId = RoleId, RoleName = ((RoleEnums)RoleId.ToInt32()).GetDescription(), - IsRoomManager = isManager + IsRoomManager = isRoomManager }; 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.GetUserJoinChannelKey(UId), roomNum, 1); pipe.EndPipe(); diff --git a/WGShare.API/Hubs/IMessageClient.cs b/WGShare.API/Hubs/IMessageClient.cs index 1e17721..46f0f9c 100644 --- a/WGShare.API/Hubs/IMessageClient.cs +++ b/WGShare.API/Hubs/IMessageClient.cs @@ -97,5 +97,11 @@ namespace WGShare.API.Hubs /// /// Task ManagerRefresh(ChannelUserInfo user); + + /// + /// 强制退出 + /// + /// + Task ForceLogout(string msg); } } diff --git a/WGShare.API/Program.cs b/WGShare.API/Program.cs index da08609..d99b658 100644 --- a/WGShare.API/Program.cs +++ b/WGShare.API/Program.cs @@ -28,7 +28,9 @@ namespace WGShare.API Serialize = (x) => x.ToJsonString(), Deserialize = (x, t) => JsonConvert.DeserializeObject(x, t), }); +#if !DEBUG ResetRedisKey(); +#endif builder.Services.Configure(options => { @@ -43,6 +45,7 @@ namespace WGShare.API options.Filters.Add(); // ȫģ͸ֵĬֵ ͳһظʽ options.Filters.Add(); + options.Filters.Add(); }).AddNewtonsoftJson(options => { //޸ƵлʽĸСдշʽ diff --git a/WGShare.API/ServiceConfigs/AuthonizationFilter.cs b/WGShare.API/ServiceConfigs/AuthonizationFilter.cs new file mode 100644 index 0000000..15ea054 --- /dev/null +++ b/WGShare.API/ServiceConfigs/AuthonizationFilter.cs @@ -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; + } + } + + } + } +} diff --git a/WGShare.API/WGShare.API.xml b/WGShare.API/WGShare.API.xml index bb69696..6e632e8 100644 --- a/WGShare.API/WGShare.API.xml +++ b/WGShare.API/WGShare.API.xml @@ -445,6 +445,12 @@ + + + 强制退出 + + + 加入频道 diff --git a/WGShare.Domain/Constant/RedisKeyConstant.cs b/WGShare.Domain/Constant/RedisKeyConstant.cs index 78eae8d..e226111 100644 --- a/WGShare.Domain/Constant/RedisKeyConstant.cs +++ b/WGShare.Domain/Constant/RedisKeyConstant.cs @@ -57,9 +57,16 @@ namespace WGShare.Domain.Constant /// /// /// - 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"; + + /// + /// 获取Accesstoken Redis Key + /// + /// + /// + public static string GetAccessTokenKey(string uid) => $@"data:access_tk:{uid}"; }