From 6533020ebcb2a66f12cec0951bafaee26b9bd0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=8D=E5=81=9A=E7=A0=81=E5=86=9C?= <599854767@qq.com> Date: Sat, 26 Aug 2023 15:54:41 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=E6=96=B0=E5=A2=9E=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E7=AB=AF=E6=89=AB=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/HttpContextExtension.cs | 51 +++++------ Infrastructure/Infrastructure.csproj | 3 +- .../Controllers/System/SysLoginController.cs | 87 +++++++++++++++++++ .../Filters/GlobalActionMonitor.cs | 11 +-- ZR.Admin.WebApi/Filters/VerifyAttribute.cs | 8 +- ZR.Admin.WebApi/GlobalUsing.cs | 3 +- .../Middleware/GlobalExceptionMiddleware.cs | 12 +-- ZR.Admin.WebApi/ZR.Admin.WebApi.csproj | 1 - ZR.Admin.WebApi/appsettings.json | 2 +- ZR.Model/System/Dto/LoginUser.cs | 3 +- ZR.Model/System/Dto/ScanDto.cs | 9 ++ ZR.Service/System/CacheService.cs | 40 ++++++++- 12 files changed, 173 insertions(+), 57 deletions(-) rename {ZR.Admin.WebApi => Infrastructure}/Extensions/HttpContextExtension.cs (92%) create mode 100644 ZR.Model/System/Dto/ScanDto.cs diff --git a/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs b/Infrastructure/Extensions/HttpContextExtension.cs similarity index 92% rename from ZR.Admin.WebApi/Extensions/HttpContextExtension.cs rename to Infrastructure/Extensions/HttpContextExtension.cs index 542065c..6b92670 100644 --- a/ZR.Admin.WebApi/Extensions/HttpContextExtension.cs +++ b/Infrastructure/Extensions/HttpContextExtension.cs @@ -1,12 +1,14 @@ -using Infrastructure; -using Infrastructure.Extensions; +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Security.Claims; using System.Text; using System.Text.RegularExpressions; using UAParser; -using ZR.Model.System; -namespace ZR.Admin.WebApi.Extensions +namespace Infrastructure.Extensions { /// /// HttpContext扩展类 @@ -82,7 +84,7 @@ namespace ZR.Admin.WebApi.Extensions /// /// /// - public static string? GetName(this HttpContext context) + public static string GetName(this HttpContext context) { var uid = context.User?.Identity?.Name; @@ -105,7 +107,7 @@ namespace ZR.Admin.WebApi.Extensions /// /// /// - public static IEnumerable? GetClaims(this HttpContext context) + public static IEnumerable GetClaims(this HttpContext context) { return context.User?.Identities; } @@ -131,26 +133,12 @@ namespace ZR.Admin.WebApi.Extensions return context.Request.Headers["Authorization"]; } - /// - /// 获取浏览器信息 - /// - /// - /// - public static ClientInfo GetClientInfo(this HttpContext context) - { - var str = context.GetUserAgent(); - var uaParser = Parser.GetDefault(); - ClientInfo c = uaParser.Parse(str); - - return c; - } - /// /// 获取请求Url /// /// /// - public static string? GetRequestUrl(this HttpContext context) + public static string GetRequestUrl(this HttpContext context) { return context != null ? context.Request.Path.Value : ""; } @@ -194,14 +182,27 @@ namespace ZR.Admin.WebApi.Extensions return body; } + /// + /// 获取浏览器信息 + /// + /// + /// + public static ClientInfo GetClientInfo(this HttpContext context) + { + var str = context.GetUserAgent(); + var uaParser = Parser.GetDefault(); + ClientInfo c = uaParser.Parse(str); + + return c; + } + /// /// 设置请求参数 /// - /// + /// /// - public static void GetRequestValue(this HttpContext context, SysOperLog operLog) + public static string GetRequestValue(this HttpContext context,string reqMethod) { - string reqMethod = operLog.RequestMethod; string param= string.Empty; if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod) || HttpMethods.IsDelete(reqMethod)) @@ -213,7 +214,7 @@ namespace ZR.Admin.WebApi.Extensions { param = context.GetQueryString(); } - operLog.OperParam = param; + return param; } [GeneratedRegex("(?<=\"password\":\")[^\",]*")] diff --git a/Infrastructure/Infrastructure.csproj b/Infrastructure/Infrastructure.csproj index c305efe..d20e088 100644 --- a/Infrastructure/Infrastructure.csproj +++ b/Infrastructure/Infrastructure.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -14,6 +14,7 @@ + diff --git a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs index a66cc7f..6105e69 100644 --- a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs +++ b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs @@ -2,6 +2,8 @@ using Lazy.Captcha.Core; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using SqlSugar; +using System.Diagnostics; using UAParser; using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Filters; @@ -72,6 +74,15 @@ namespace ZR.Admin.WebApi.Controllers.System return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误"); } + var lockTimeStamp = CacheService.GetLockUser(loginBody.ClientId); + var lockTime = DateTimeHelper.ToLocalTimeDateBySeconds(lockTimeStamp); + var ts = lockTime - DateTime.Now; + + if (lockTimeStamp > 0 && ts.TotalSeconds > 0) + { + return ToResponse(ResultCode.LOGIN_ERROR, $"你的账号已被锁,剩余{Math.Round(ts.TotalMinutes, 0)}分钟"); + } + var user = sysLoginService.Login(loginBody, RecordLogInfo(httpContextAccessor.HttpContext)); List roles = roleService.SelectUserRoleListByUserId(user.UserId); @@ -205,5 +216,81 @@ namespace ZR.Admin.WebApi.Controllers.System } return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员"); } + + #region 二维码登录 + + /// + /// 生成二维码 + /// + /// + /// + /// + [HttpGet("/GenerateQrcode")] + public IActionResult GenerateQrcode(string uuid, string deviceId) + { + var state = Guid.NewGuid().ToString(); + var dict = new Dictionary + { + { "state", state } + }; + CacheService.SetScanLogin(uuid, dict); + return SUCCESS(new + { + status = 1, + state, + uuid, + codeContent = new { uuid, deviceId }// "https://qm.qq.com/cgi-bin/qm/qr?k=kgt4HsckdljU0VM-0kxND6d_igmfuPlL&authKey=r55YUbruiKQ5iwC/folG7KLCmZ++Y4rQVgNlvLbUniUMkbk24Y9+zNuOmOnjAjRc&noverify=0" + }); + } + + /// + /// 轮询判断扫码状态 + /// + /// + /// + [HttpPost("/VerifyScan")] + [AllowAnonymous] + public IActionResult VerifyScan([FromBody] ScanDto dto) + { + int status = -1; + object token = string.Empty; + if (CacheService.GetScanLogin(dto.Uuid) is Dictionary str) + { + status = 0; + str.TryGetValue("token", out token); + if (str.ContainsKey("status") && (string)str.GetValueOrDefault("status") == "success") + { + status = 2;//扫码成功 + CacheService.RemoveScanLogin(dto.Uuid); + } + } + + return SUCCESS(new { status, token }); + } + + /// + /// 移动端扫码登录 + /// + /// + /// + [HttpPost("/ScanLogin")] + [Log(Title = "扫码登录")] + public IActionResult ScanLogin([FromBody] ScanDto dto) + { + if (dto == null) { return ToResponse(ResultCode.CUSTOM_ERROR, "扫码失败"); } + + var token = HttpContextExtension.GetToken(HttpContext); + if (CacheService.GetScanLogin(dto.Uuid) is not null) + { + Dictionary dict = new() { }; + dict.Add("status", "success"); + dict.Add("token", token.Replace("Bearer ", "")); + CacheService.SetScanLogin(dto.Uuid, dict); + //TODO 待优化,应该生成新的token + return SUCCESS(1); + } + return ToResponse(ResultCode.FAIL, "二维码已失效"); + } + #endregion } } diff --git a/ZR.Admin.WebApi/Filters/GlobalActionMonitor.cs b/ZR.Admin.WebApi/Filters/GlobalActionMonitor.cs index a4c00fa..1f11e79 100644 --- a/ZR.Admin.WebApi/Filters/GlobalActionMonitor.cs +++ b/ZR.Admin.WebApi/Filters/GlobalActionMonitor.cs @@ -1,12 +1,9 @@ -using Infrastructure; -using Infrastructure.Attribute; -using Infrastructure.Model; +using Infrastructure.Extensions; using IPTools.Core; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using NLog; -using ZR.Admin.WebApi.Extensions; using ZR.Model.System; using ZR.Service.System.IService; @@ -104,9 +101,9 @@ namespace ZR.Admin.WebApi.Filters OperLocation = ip_info.Province + " " + ip_info.City, Method = controller + "." + action + "()", //Elapsed = _stopwatch.ElapsedMilliseconds, - OperTime = DateTime.Now + OperTime = DateTime.Now, + OperParam = HttpContextExtension.GetRequestValue(context.HttpContext, method) }; - HttpContextExtension.GetRequestValue(context.HttpContext, sysOperLog); if (logAttribute != null) { @@ -117,7 +114,7 @@ namespace ZR.Admin.WebApi.Filters } LogEventInfo ei = new(NLog.LogLevel.Info, "GlobalActionMonitor", ""); - + ei.Properties["jsonResult"] = !HttpMethods.IsGet(method) ? jsonResult : ""; ei.Properties["requestParam"] = sysOperLog.OperParam; ei.Properties["user"] = userName; diff --git a/ZR.Admin.WebApi/Filters/VerifyAttribute.cs b/ZR.Admin.WebApi/Filters/VerifyAttribute.cs index a925b3e..5e54c93 100644 --- a/ZR.Admin.WebApi/Filters/VerifyAttribute.cs +++ b/ZR.Admin.WebApi/Filters/VerifyAttribute.cs @@ -1,13 +1,7 @@ -using Infrastructure; -using Infrastructure.Model; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using NLog; -using System; -using System.Linq; -using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Framework; using ZR.Model.System.Dto; diff --git a/ZR.Admin.WebApi/GlobalUsing.cs b/ZR.Admin.WebApi/GlobalUsing.cs index 4d4888f..37d1b22 100644 --- a/ZR.Admin.WebApi/GlobalUsing.cs +++ b/ZR.Admin.WebApi/GlobalUsing.cs @@ -4,4 +4,5 @@ global using Infrastructure; global using Infrastructure.Attribute; global using Infrastructure.Enums; global using Infrastructure.Model; -global using Mapster; \ No newline at end of file +global using Mapster; +global using Infrastructure.Extensions; \ No newline at end of file diff --git a/ZR.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs b/ZR.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs index 3ee7baa..7668a2e 100644 --- a/ZR.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs +++ b/ZR.Admin.WebApi/Middleware/GlobalExceptionMiddleware.cs @@ -1,14 +1,8 @@ -using Infrastructure; -using Infrastructure.Attribute; -using Infrastructure.Model; -using IPTools.Core; +using IPTools.Core; using Microsoft.AspNetCore.Http.Features; using NLog; -using System.Diagnostics; using System.Text.Encodings.Web; using System.Text.Json; -using ZR.Admin.WebApi.Extensions; -using ZR.Common; using ZR.Model.System; using ZR.Service.System.IService; @@ -90,9 +84,9 @@ namespace ZR.Admin.WebApi.Middleware ErrorMsg = string.IsNullOrEmpty(error) ? msg : error, OperName = HttpContextExtension.GetName(context), OperLocation = ip_info.Province + " " + ip_info.City, - OperTime = DateTime.Now + OperTime = DateTime.Now, + OperParam = HttpContextExtension.GetRequestValue(context, context.Request.Method) }; - HttpContextExtension.GetRequestValue(context, sysOperLog); var endpoint = GetEndpoint(context); if (endpoint != null) { diff --git a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj index 3acc417..7e82c93 100644 --- a/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj +++ b/ZR.Admin.WebApi/ZR.Admin.WebApi.csproj @@ -20,7 +20,6 @@ - diff --git a/ZR.Admin.WebApi/appsettings.json b/ZR.Admin.WebApi/appsettings.json index 7161d38..9a3cf89 100644 --- a/ZR.Admin.WebApi/appsettings.json +++ b/ZR.Admin.WebApi/appsettings.json @@ -109,7 +109,7 @@ "RealIpHeader": "X-Real-IP", "ClientIdHeader": "X-ClientId", "HttpStatusCode": 429, - "EndpointWhitelist": [ "post:/system/dict/data/types", "*:/msghub/negotiate", "*:/LogOut", "*:/common/uploadfile" ], + "EndpointWhitelist": [ "post:/system/dict/data/types", "*:/msghub/negotiate", "*:/LogOut", "*:/common/uploadfile", "*:/VerifyScan" ], "QuotaExceededResponse": { "Content": "{{\"code\":429,\"msg\":\"访问过于频繁,请稍后重试\"}}", "ContentType": "application/json", diff --git a/ZR.Model/System/Dto/LoginUser.cs b/ZR.Model/System/Dto/LoginUser.cs index 8bf08d7..c06f742 100644 --- a/ZR.Model/System/Dto/LoginUser.cs +++ b/ZR.Model/System/Dto/LoginUser.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; namespace ZR.Model.System.Dto { diff --git a/ZR.Model/System/Dto/ScanDto.cs b/ZR.Model/System/Dto/ScanDto.cs new file mode 100644 index 0000000..063108e --- /dev/null +++ b/ZR.Model/System/Dto/ScanDto.cs @@ -0,0 +1,9 @@ +namespace ZR.Model.System.Dto +{ + public class ScanDto + { + public string Uuid { get; set; } + public string State { get; set; } + public string DeviceId { get; set; } + } +} diff --git a/ZR.Service/System/CacheService.cs b/ZR.Service/System/CacheService.cs index 1b5a336..7ba1ead 100644 --- a/ZR.Service/System/CacheService.cs +++ b/ZR.Service/System/CacheService.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; -using System.Linq; +using System; using ZR.Common; -using ZR.Common.Cache; namespace ZR.Service.System { public class CacheService { + private readonly static string CK_verifyScan = "verifyScan_"; #region 用户权限 缓存 public static List GetUserPerms(string key) { @@ -25,5 +24,40 @@ namespace ZR.Service.System //RedisServer.Cache.Del(key); } #endregion + + public static object SetScanLogin(string key, Dictionary val) + { + var ck = CK_verifyScan + key; + + return CacheHelper.SetCache(ck,val , 1); + } + public static object GetScanLogin(string key) + { + var ck = CK_verifyScan + key; + return CacheHelper.Get(ck); + } + public static void RemoveScanLogin(string key) + { + var ck = CK_verifyScan + key; + CacheHelper.Remove(ck); + } + + public static void SetLockUser(string key, long val, int time) + { + var CK = "lock_user_" + key; + + CacheHelper.SetCache(CK, val, time); + } + + public static long GetLockUser(string key) + { + var CK = "lock_user_" + key; + + if (CacheHelper.Get(CK) is long t) + { + return t; + } + return 0; + } } }