优化登录

This commit is contained in:
不做码农 2023-08-28 22:16:57 +08:00
parent ea3fa0e0d6
commit 52240ab6a8
12 changed files with 81 additions and 58 deletions

View File

@ -5,8 +5,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal;
using System.Xml.Linq;
namespace Infrastructure namespace Infrastructure
{ {

View File

@ -15,6 +15,7 @@
<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" /> <PackageReference Include="UAParser" Version="3.1.47" />
<PackageReference Include="IPTools.China" Version="1.6.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,5 @@
using Infrastructure.Extensions; using Infrastructure.Extensions;
using IPTools.Core;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -197,14 +198,24 @@ namespace Infrastructure.WebExtensins
return c; return c;
} }
/// <summary>
/// 根据IP获取地理位置
/// </summary>
/// <returns></returns>
public static string GetIpInfo(string IP)
{
var ipInfo = IpTool.Search(IP);
return ipInfo?.Province + "-" + ipInfo?.City + "-" + ipInfo?.NetworkOperator;
}
/// <summary> /// <summary>
/// 设置请求参数 /// 设置请求参数
/// </summary> /// </summary>
/// <param name="reqMethod"></param> /// <param name="reqMethod"></param>
/// <param name="context"></param> /// <param name="context"></param>
public static string GetRequestValue(this HttpContext context,string reqMethod) public static string GetRequestValue(this HttpContext context, string reqMethod)
{ {
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))
{ {

View File

@ -195,6 +195,7 @@ Vue 版前端技术栈 :基于 vue2.x/vue3.x/uniapp、vuex、vue-router 、vue
- 👉SqlSugar[SqlSugar](https://gitee.com/dotnetchina/SqlSugar) - 👉SqlSugar[SqlSugar](https://gitee.com/dotnetchina/SqlSugar)
- 👉vue-element-admin[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) - 👉vue-element-admin[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- 👉Meiam.System[Meiam.System](https://github.com/91270/Meiam.System) - 👉Meiam.System[Meiam.System](https://github.com/91270/Meiam.System)
- 👉Furion[Furion](https://gitee.com/dotnetchina/Furion)
## 🎀 捐赠 ## 🎀 捐赠

View File

@ -79,13 +79,14 @@ namespace ZR.Admin.WebApi.Controllers.System
{ {
return ToResponse(ResultCode.LOGIN_ERROR, $"你的账号已被锁,剩余{Math.Round(ts.TotalMinutes, 0)}分钟"); return ToResponse(ResultCode.LOGIN_ERROR, $"你的账号已被锁,剩余{Math.Round(ts.TotalMinutes, 0)}分钟");
} }
var user = sysLoginService.Login(loginBody, RecordLogInfo(httpContextAccessor.HttpContext)); string location = HttpContextExtension.GetIpInfo(loginBody.LoginIP);
var user = sysLoginService.Login(loginBody, new SysLogininfor() { LoginLocation = location });
List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId); List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
//权限集合 eg *:*:*,system:user:list //权限集合 eg *:*:*,system:user:list
List<string> permissions = permissionService.GetMenuPermission(user); List<string> permissions = permissionService.GetMenuPermission(user);
LoginUser loginUser = new(user, roles); LoginUser loginUser = new(user, roles.Adapt<List<Roles>>());
CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.UserId, permissions); CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.UserId, permissions);
return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser))); return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser)));
} }
@ -128,8 +129,6 @@ namespace ZR.Admin.WebApi.Controllers.System
List<string> permissions = permissionService.GetMenuPermission(user); List<string> permissions = permissionService.GetMenuPermission(user);
user.WelcomeContent = GlobalConstant.WelcomeMessages[new Random().Next(0, GlobalConstant.WelcomeMessages.Length)]; user.WelcomeContent = GlobalConstant.WelcomeMessages[new Random().Next(0, GlobalConstant.WelcomeMessages.Length)];
//LoginUser loginUser = new(user, roleService.SelectUserRoleListByUserId(user.UserId), permissions);
//var token = JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser), optionSettings.JwtSettings);
return SUCCESS(new { user, roles, permissions }); return SUCCESS(new { user, roles, permissions });
} }
@ -164,29 +163,6 @@ namespace ZR.Admin.WebApi.Controllers.System
return SUCCESS(obj); return SUCCESS(obj);
} }
/// <summary>
/// 记录用户登陆信息
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
[ApiExplorerSettings(IgnoreApi = true)]
public SysLogininfor RecordLogInfo(HttpContext context)
{
var ipAddr = context.GetClientUserIp();
var ip_info = IpTool.Search(ipAddr);
ClientInfo clientInfo = context.GetClientInfo();
SysLogininfor sysLogininfor = new()
{
Browser = clientInfo.ToString(),
Os = clientInfo.OS.ToString(),
Ipaddr = ipAddr,
UserName = context.GetName(),
LoginLocation = ip_info?.Province + "-" + ip_info?.City
};
return sysLogininfor;
}
/// <summary> /// <summary>
/// 注册 /// 注册
/// </summary> /// </summary>

View File

@ -1,5 +1,4 @@
using Infrastructure.Extensions; 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;
@ -26,9 +25,7 @@ namespace ZR.Admin.WebApi.Filters
/// <returns></returns> /// <returns></returns>
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{ {
ApiResult response = new(); string msg = string.Empty;
response.Code = (int)ResultCode.PARAM_ERROR;
var values = context.ModelState.Values; var values = context.ModelState.Values;
foreach (var item in values) foreach (var item in values)
{ {
@ -38,17 +35,22 @@ namespace ZR.Admin.WebApi.Filters
{ {
return next(); return next();
} }
if (!string.IsNullOrEmpty(response.Msg)) if (!string.IsNullOrEmpty(msg))
{ {
response.Msg += " | "; msg += " | ";
} }
response.Msg += err.ErrorMessage; msg += err.ErrorMessage;
} }
} }
if (!string.IsNullOrEmpty(response.Msg)) if (!string.IsNullOrEmpty(msg))
{ {
logger.Info($"请求参数错误,{response.Msg}"); logger.Info($"请求参数错误,{msg}");
ApiResult response = new()
{
Code = (int)ResultCode.PARAM_ERROR,
Msg = msg
};
context.Result = new JsonResult(response); context.Result = new JsonResult(response);
} }
return base.OnActionExecutionAsync(context, next); return base.OnActionExecutionAsync(context, next);
@ -98,7 +100,7 @@ namespace ZR.Admin.WebApi.Filters
OperUrl = HttpContextExtension.GetRequestUrl(context.HttpContext), OperUrl = HttpContextExtension.GetRequestUrl(context.HttpContext),
RequestMethod = method, RequestMethod = method,
JsonResult = jsonResult, JsonResult = jsonResult,
OperLocation = ip_info.Province + " " + ip_info.City, OperLocation = HttpContextExtension.GetIpInfo(ip),
Method = controller + "." + action + "()", Method = controller + "." + action + "()",
//Elapsed = _stopwatch.ElapsedMilliseconds, //Elapsed = _stopwatch.ElapsedMilliseconds,
OperTime = DateTime.Now, OperTime = DateTime.Now,

View File

@ -1,8 +1,13 @@
using Microsoft.IdentityModel.Tokens; using JinianNet.JNTemplate;
using JinianNet.JNTemplate.Nodes;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using System.Security.Claims;
using System.Text; using System.Text;
using ZR.Admin.WebApi.Hubs;
using ZR.Model.System.Dto; using ZR.Model.System.Dto;
namespace ZR.Admin.WebApi.Framework namespace ZR.Admin.WebApi.Framework
@ -122,7 +127,8 @@ namespace ZR.Admin.WebApi.Framework
{ {
try try
{ {
IEnumerable<Claim> claims = jwtSecurityToken.Claims; if (jwtSecurityToken == null) return null;
IEnumerable<Claim> claims = jwtSecurityToken?.Claims;
LoginUser loginUser = null; LoginUser loginUser = null;
var userData = claims.FirstOrDefault(x => x.Type == ClaimTypes.UserData)?.Value; var userData = claims.FirstOrDefault(x => x.Type == ClaimTypes.UserData)?.Value;
@ -131,7 +137,21 @@ namespace ZR.Admin.WebApi.Framework
loginUser = JsonConvert.DeserializeObject<LoginUser>(userData); loginUser = JsonConvert.DeserializeObject<LoginUser>(userData);
loginUser.ExpireTime = jwtSecurityToken.ValidTo; loginUser.ExpireTime = jwtSecurityToken.ValidTo;
} }
//Console.WriteLine("jwt到期时间" + validTo); //var nowTime = DateTime.UtcNow;
//TimeSpan ts = loginUser.ExpireTime - nowTime;
//Console.WriteLine("jwt到期时间" + loginUser.ExpireTime);
//Console.WriteLine("nowTime" + nowTime + ",相隔" + ts.TotalSeconds);
//if (loginUser != null && ts.TotalSeconds <= 30)
//{
// var newToken = GenerateJwtToken(AddClaims(loginUser));
// var CK = "token_" + loginUser.UserId;
// if (!CacheHelper.Exists(CK))
// {
// CacheHelper.SetCache(CK, newToken);
// }
//}
return loginUser; return loginUser;
} }
catch (Exception ex) catch (Exception ex)

View File

@ -10,6 +10,7 @@ using ZR.Admin.WebApi.Framework;
using ZR.Admin.WebApi.Hubs; using ZR.Admin.WebApi.Hubs;
using ZR.Admin.WebApi.Middleware; using ZR.Admin.WebApi.Middleware;
using ZR.Common.Cache; using ZR.Common.Cache;
using ZR.Model.System.Dto;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -54,11 +55,12 @@ builder.Services.AddAuthentication(options =>
// 如果过期,把过期信息添加到头部 // 如果过期,把过期信息添加到头部
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{ {
Console.WriteLine("jwt过期了");
context.Response.Headers.Add("Token-Expired", "true"); context.Response.Headers.Add("Token-Expired", "true");
} }
return Task.CompletedTask; return Task.CompletedTask;
} },
}; };
}); });

View File

@ -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="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" />
<PackageReference Include="Mapster" Version="7.3.0" /> <PackageReference Include="Mapster" Version="7.3.0" />

View File

@ -17,7 +17,7 @@ namespace ZR.Model.System.Dto
/// <summary> /// <summary>
/// 角色集合(数据权限过滤使用) /// 角色集合(数据权限过滤使用)
/// </summary> /// </summary>
public List<SysRole> Roles { get; set; } public List<Roles> Roles { get; set; }
/// <summary> /// <summary>
/// Jwt过期时间 /// Jwt过期时间
/// </summary> /// </summary>
@ -30,7 +30,7 @@ namespace ZR.Model.System.Dto
{ {
} }
public LoginUser(SysUser user, List<SysRole> roles) public LoginUser(SysUser user, List<Roles> roles)
{ {
UserId = user.UserId; UserId = user.UserId;
UserName = user.UserName; UserName = user.UserName;
@ -39,4 +39,11 @@ namespace ZR.Model.System.Dto
RoleIds = roles.Select(f => f.RoleKey).ToList(); RoleIds = roles.Select(f => f.RoleKey).ToList();
} }
} }
public class Roles
{
public long RoleId { get; set; }
public string RoleKey { get; set; }
public int DataScope { get; set; }
}
} }

View File

@ -1,9 +1,6 @@
using System; using ZR.Model;
using System.Collections.Generic;
using System.Text;
using ZR.Model;
using ZR.Model.System.Dto;
using ZR.Model.System; using ZR.Model.System;
using ZR.Model.System.Dto;
namespace ZR.Service.System.IService namespace ZR.Service.System.IService
{ {

View File

@ -1,8 +1,11 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Attribute; using Infrastructure.Attribute;
using Infrastructure.Extensions; using Infrastructure.Extensions;
using Infrastructure.WebExtensins;
using Microsoft.AspNetCore.Http;
using SqlSugar; using SqlSugar;
using System; using System;
using UAParser;
using ZR.Model; using ZR.Model;
using ZR.Model.System; using ZR.Model.System;
using ZR.Model.System.Dto; using ZR.Model.System.Dto;
@ -15,13 +18,15 @@ namespace ZR.Service.System
/// 登录 /// 登录
/// </summary> /// </summary>
[AppService(ServiceType = typeof(ISysLoginService), ServiceLifetime = LifeTime.Transient)] [AppService(ServiceType = typeof(ISysLoginService), ServiceLifetime = LifeTime.Transient)]
public class SysLoginService: BaseService<SysLogininfor>, ISysLoginService public class SysLoginService : BaseService<SysLogininfor>, ISysLoginService
{ {
private readonly ISysUserService SysUserService; private readonly ISysUserService SysUserService;
private readonly IHttpContextAccessor httpContextAccessor;
public SysLoginService(ISysUserService sysUserService) public SysLoginService(ISysUserService sysUserService, IHttpContextAccessor httpContextAccessor)
{ {
SysUserService = sysUserService; SysUserService = sysUserService;
this.httpContextAccessor = httpContextAccessor;
} }
/// <summary> /// <summary>
@ -35,17 +40,21 @@ namespace ZR.Service.System
{ {
loginBody.Password = NETCore.Encrypt.EncryptProvider.Md5(loginBody.Password); loginBody.Password = NETCore.Encrypt.EncryptProvider.Md5(loginBody.Password);
} }
SysUser user = SysUserService.Login(loginBody); SysUser user = SysUserService.Login(loginBody);
logininfor.UserName = loginBody.Username; logininfor.UserName = loginBody.Username;
logininfor.Status = "1"; logininfor.Status = "1";
logininfor.LoginTime = DateTime.Now; logininfor.LoginTime = DateTime.Now;
logininfor.Ipaddr = loginBody.LoginIP;
ClientInfo clientInfo = httpContextAccessor.HttpContext.GetClientInfo();
logininfor.Browser = clientInfo.ToString();
logininfor.Os = clientInfo.OS.ToString();
if (user == null || user.UserId <= 0) if (user == null || user.UserId <= 0)
{ {
logininfor.Msg = "用户名或密码错误"; logininfor.Msg = "用户名或密码错误";
AddLoginInfo(logininfor); AddLoginInfo(logininfor);
throw new CustomException(ResultCode.LOGIN_ERROR ,logininfor.Msg); throw new CustomException(ResultCode.LOGIN_ERROR, logininfor.Msg);
} }
if (user.Status == 1) if (user.Status == 1)
{ {