✨新增移动端扫码登录
This commit is contained in:
parent
710966e098
commit
6533020ebc
@ -1,12 +1,14 @@
|
|||||||
using Infrastructure;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Infrastructure.Extensions;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using UAParser;
|
using UAParser;
|
||||||
using ZR.Model.System;
|
|
||||||
|
|
||||||
namespace ZR.Admin.WebApi.Extensions
|
namespace Infrastructure.Extensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HttpContext扩展类
|
/// HttpContext扩展类
|
||||||
@ -82,7 +84,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string? GetName(this HttpContext context)
|
public static string GetName(this HttpContext context)
|
||||||
{
|
{
|
||||||
var uid = context.User?.Identity?.Name;
|
var uid = context.User?.Identity?.Name;
|
||||||
|
|
||||||
@ -105,7 +107,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IEnumerable<ClaimsIdentity>? GetClaims(this HttpContext context)
|
public static IEnumerable<ClaimsIdentity> GetClaims(this HttpContext context)
|
||||||
{
|
{
|
||||||
return context.User?.Identities;
|
return context.User?.Identities;
|
||||||
}
|
}
|
||||||
@ -131,26 +133,12 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
return context.Request.Headers["Authorization"];
|
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>
|
/// <summary>
|
||||||
/// 获取请求Url
|
/// 获取请求Url
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string? GetRequestUrl(this HttpContext context)
|
public static string GetRequestUrl(this HttpContext context)
|
||||||
{
|
{
|
||||||
return context != null ? context.Request.Path.Value : "";
|
return context != null ? context.Request.Path.Value : "";
|
||||||
}
|
}
|
||||||
@ -194,14 +182,27 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
return body;
|
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>
|
||||||
/// 设置请求参数
|
/// 设置请求参数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="operLog"></param>
|
/// <param name="reqMethod"></param>
|
||||||
/// <param name="context"></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;
|
string param= string.Empty;
|
||||||
|
|
||||||
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod) || HttpMethods.IsDelete(reqMethod))
|
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod) || HttpMethods.IsDelete(reqMethod))
|
||||||
@ -213,7 +214,7 @@ namespace ZR.Admin.WebApi.Extensions
|
|||||||
{
|
{
|
||||||
param = context.GetQueryString();
|
param = context.GetQueryString();
|
||||||
}
|
}
|
||||||
operLog.OperParam = param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex("(?<=\"password\":\")[^\",]*")]
|
[GeneratedRegex("(?<=\"password\":\")[^\",]*")]
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -14,6 +14,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="7.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
using Lazy.Captcha.Core;
|
using Lazy.Captcha.Core;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using SqlSugar;
|
||||||
|
using System.Diagnostics;
|
||||||
using UAParser;
|
using UAParser;
|
||||||
using ZR.Admin.WebApi.Extensions;
|
using ZR.Admin.WebApi.Extensions;
|
||||||
using ZR.Admin.WebApi.Filters;
|
using ZR.Admin.WebApi.Filters;
|
||||||
@ -72,6 +74,15 @@ namespace ZR.Admin.WebApi.Controllers.System
|
|||||||
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
|
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));
|
var user = sysLoginService.Login(loginBody, RecordLogInfo(httpContextAccessor.HttpContext));
|
||||||
|
|
||||||
List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
|
List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
|
||||||
@ -205,5 +216,81 @@ namespace ZR.Admin.WebApi.Controllers.System
|
|||||||
}
|
}
|
||||||
return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员");
|
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.Extensions;
|
||||||
using Infrastructure.Attribute;
|
|
||||||
using Infrastructure.Model;
|
|
||||||
using IPTools.Core;
|
using IPTools.Core;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using NLog;
|
using NLog;
|
||||||
using ZR.Admin.WebApi.Extensions;
|
|
||||||
using ZR.Model.System;
|
using ZR.Model.System;
|
||||||
using ZR.Service.System.IService;
|
using ZR.Service.System.IService;
|
||||||
|
|
||||||
@ -104,9 +101,9 @@ namespace ZR.Admin.WebApi.Filters
|
|||||||
OperLocation = ip_info.Province + " " + ip_info.City,
|
OperLocation = ip_info.Province + " " + ip_info.City,
|
||||||
Method = controller + "." + action + "()",
|
Method = controller + "." + action + "()",
|
||||||
//Elapsed = _stopwatch.ElapsedMilliseconds,
|
//Elapsed = _stopwatch.ElapsedMilliseconds,
|
||||||
OperTime = DateTime.Now
|
OperTime = DateTime.Now,
|
||||||
|
OperParam = HttpContextExtension.GetRequestValue(context.HttpContext, method)
|
||||||
};
|
};
|
||||||
HttpContextExtension.GetRequestValue(context.HttpContext, sysOperLog);
|
|
||||||
|
|
||||||
if (logAttribute != null)
|
if (logAttribute != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
using Infrastructure;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Infrastructure.Model;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using ZR.Admin.WebApi.Extensions;
|
|
||||||
using ZR.Admin.WebApi.Framework;
|
using ZR.Admin.WebApi.Framework;
|
||||||
using ZR.Model.System.Dto;
|
using ZR.Model.System.Dto;
|
||||||
|
|
||||||
|
|||||||
@ -5,3 +5,4 @@ global using Infrastructure.Attribute;
|
|||||||
global using Infrastructure.Enums;
|
global using Infrastructure.Enums;
|
||||||
global using Infrastructure.Model;
|
global using Infrastructure.Model;
|
||||||
global using Mapster;
|
global using Mapster;
|
||||||
|
global using Infrastructure.Extensions;
|
||||||
@ -1,14 +1,8 @@
|
|||||||
using Infrastructure;
|
using IPTools.Core;
|
||||||
using Infrastructure.Attribute;
|
|
||||||
using Infrastructure.Model;
|
|
||||||
using IPTools.Core;
|
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using ZR.Admin.WebApi.Extensions;
|
|
||||||
using ZR.Common;
|
|
||||||
using ZR.Model.System;
|
using ZR.Model.System;
|
||||||
using ZR.Service.System.IService;
|
using ZR.Service.System.IService;
|
||||||
|
|
||||||
@ -90,9 +84,9 @@ namespace ZR.Admin.WebApi.Middleware
|
|||||||
ErrorMsg = string.IsNullOrEmpty(error) ? msg : error,
|
ErrorMsg = string.IsNullOrEmpty(error) ? msg : error,
|
||||||
OperName = HttpContextExtension.GetName(context),
|
OperName = HttpContextExtension.GetName(context),
|
||||||
OperLocation = ip_info.Province + " " + ip_info.City,
|
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);
|
var endpoint = GetEndpoint(context);
|
||||||
if (endpoint != null)
|
if (endpoint != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.7" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.7" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" />
|
<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="IPTools.China" Version="1.6.0" />
|
||||||
<PackageReference Include="NLog" Version="5.2.3" />
|
<PackageReference Include="NLog" Version="5.2.3" />
|
||||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.3" />
|
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.3" />
|
||||||
|
|||||||
@ -109,7 +109,7 @@
|
|||||||
"RealIpHeader": "X-Real-IP",
|
"RealIpHeader": "X-Real-IP",
|
||||||
"ClientIdHeader": "X-ClientId",
|
"ClientIdHeader": "X-ClientId",
|
||||||
"HttpStatusCode": 429,
|
"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": {
|
"QuotaExceededResponse": {
|
||||||
"Content": "{{\"code\":429,\"msg\":\"访问过于频繁,请稍后重试\"}}",
|
"Content": "{{\"code\":429,\"msg\":\"访问过于频繁,请稍后重试\"}}",
|
||||||
"ContentType": "application/json",
|
"ContentType": "application/json",
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Linq;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace ZR.Model.System.Dto
|
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;
|
||||||
using System.Linq;
|
|
||||||
using ZR.Common;
|
using ZR.Common;
|
||||||
using ZR.Common.Cache;
|
|
||||||
|
|
||||||
namespace ZR.Service.System
|
namespace ZR.Service.System
|
||||||
{
|
{
|
||||||
public class CacheService
|
public class CacheService
|
||||||
{
|
{
|
||||||
|
private readonly static string CK_verifyScan = "verifyScan_";
|
||||||
#region 用户权限 缓存
|
#region 用户权限 缓存
|
||||||
public static List<string> GetUserPerms(string key)
|
public static List<string> GetUserPerms(string key)
|
||||||
{
|
{
|
||||||
@ -25,5 +24,40 @@ namespace ZR.Service.System
|
|||||||
//RedisServer.Cache.Del(key);
|
//RedisServer.Cache.Del(key);
|
||||||
}
|
}
|
||||||
#endregion
|
#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