✨新增移动端扫码登录
This commit is contained in:
parent
710966e098
commit
6533020ebc
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// HttpContext扩展类
|
||||
@ -82,7 +84,7 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
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
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<ClaimsIdentity>? GetClaims(this HttpContext context)
|
||||
public static IEnumerable<ClaimsIdentity> GetClaims(this HttpContext context)
|
||||
{
|
||||
return context.User?.Identities;
|
||||
}
|
||||
@ -131,26 +133,12 @@ namespace ZR.Admin.WebApi.Extensions
|
||||
return context.Request.Headers["Authorization"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static ClientInfo GetClientInfo(this HttpContext context)
|
||||
{
|
||||
var str = context.GetUserAgent();
|
||||
var uaParser = Parser.GetDefault();
|
||||
ClientInfo c = uaParser.Parse(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求Url
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取浏览器信息
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public static ClientInfo GetClientInfo(this HttpContext context)
|
||||
{
|
||||
var str = context.GetUserAgent();
|
||||
var uaParser = Parser.GetDefault();
|
||||
ClientInfo c = uaParser.Parse(str);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置请求参数
|
||||
/// </summary>
|
||||
/// <param name="operLog"></param>
|
||||
/// <param name="reqMethod"></param>
|
||||
/// <param name="context"></param>
|
||||
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\":\")[^\",]*")]
|
||||
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
@ -14,6 +14,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -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<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
|
||||
@ -205,5 +216,81 @@ namespace ZR.Admin.WebApi.Controllers.System
|
||||
}
|
||||
return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员");
|
||||
}
|
||||
|
||||
#region 二维码登录
|
||||
|
||||
/// <summary>
|
||||
/// 生成二维码
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="deviceId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("/GenerateQrcode")]
|
||||
public IActionResult GenerateQrcode(string uuid, string deviceId)
|
||||
{
|
||||
var state = Guid.NewGuid().ToString();
|
||||
var dict = new Dictionary<string, object>
|
||||
{
|
||||
{ "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"
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询判断扫码状态
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("/VerifyScan")]
|
||||
[AllowAnonymous]
|
||||
public IActionResult VerifyScan([FromBody] ScanDto dto)
|
||||
{
|
||||
int status = -1;
|
||||
object token = string.Empty;
|
||||
if (CacheService.GetScanLogin(dto.Uuid) is Dictionary<string, object> 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 });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移动端扫码登录
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <returns></returns>
|
||||
[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<string, object> 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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -4,4 +4,5 @@ global using Infrastructure;
|
||||
global using Infrastructure.Attribute;
|
||||
global using Infrastructure.Enums;
|
||||
global using Infrastructure.Model;
|
||||
global using Mapster;
|
||||
global using Mapster;
|
||||
global using Infrastructure.Extensions;
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -20,7 +20,6 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.7" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="IPTools.China" Version="1.6.0" />
|
||||
<PackageReference Include="NLog" Version="5.2.3" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.3" />
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace ZR.Model.System.Dto
|
||||
{
|
||||
|
||||
9
ZR.Model/System/Dto/ScanDto.cs
Normal file
9
ZR.Model/System/Dto/ScanDto.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -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<string> GetUserPerms(string key)
|
||||
{
|
||||
@ -25,5 +24,40 @@ namespace ZR.Service.System
|
||||
//RedisServer.Cache.Del(key);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static object SetScanLogin(string key, Dictionary<string, object> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user