diff --git a/Infrastructure/Helper/RandomHelper.cs b/Infrastructure/Helper/RandomHelper.cs
new file mode 100644
index 0000000..ca8e859
--- /dev/null
+++ b/Infrastructure/Helper/RandomHelper.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Text;
+
+namespace ZR.Infrastructure.Helper
+{
+ public class RandomHelper
+ {
+ ///
+ /// 生成n为验证码
+ ///
+ ///
+ ///
+ public static string GenerateNum(int Length)
+ {
+ char[] constant = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+ StringBuilder newRandom = new(constant.Length);
+ Random rd = new();
+ for (int i = 0; i < Length; i++)
+ {
+ newRandom.Append(constant[rd.Next(constant.Length - 1)]);
+ }
+ return newRandom.ToString();
+ }
+ }
+}
diff --git a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs
index 217881c..d4c7599 100644
--- a/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs
+++ b/ZR.Admin.WebApi/Controllers/System/SysLoginController.cs
@@ -1,10 +1,13 @@
using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Mvc;
using ZR.Admin.WebApi.Filters;
+using ZR.Infrastructure.Helper;
using ZR.Model.System;
using ZR.Model.System.Dto;
using ZR.Service.System;
using ZR.Service.System.IService;
+using ZR.ServiceCore.Model.Dto;
+using ZR.ServiceCore.Services;
namespace ZR.Admin.WebApi.Controllers.System
{
@@ -21,6 +24,7 @@ namespace ZR.Admin.WebApi.Controllers.System
private readonly ICaptcha SecurityCodeHelper;
private readonly ISysConfigService sysConfigService;
private readonly ISysRoleService roleService;
+ private readonly ISmsCodeLogService smsCodeLogService;
public SysLoginController(
ISysMenuService sysMenuService,
@@ -29,6 +33,7 @@ namespace ZR.Admin.WebApi.Controllers.System
ISysPermissionService permissionService,
ISysConfigService configService,
ISysRoleService sysRoleService,
+ ISmsCodeLogService smsCodeLogService,
ICaptcha captcha)
{
SecurityCodeHelper = captcha;
@@ -37,6 +42,7 @@ namespace ZR.Admin.WebApi.Controllers.System
this.sysLoginService = sysLoginService;
this.permissionService = permissionService;
this.sysConfigService = configService;
+ this.smsCodeLogService = smsCodeLogService;
roleService = sysRoleService;
}
@@ -236,7 +242,7 @@ namespace ZR.Admin.WebApi.Controllers.System
{
if (dto == null) { return ToResponse(ResultCode.CUSTOM_ERROR, "扫码失败"); }
var name = App.HttpContext.GetName();
-
+
sysLoginService.CheckLockUser(name);
TokenModel tokenModel = JwtUtil.GetLoginUser(HttpContext);
@@ -246,12 +252,80 @@ namespace ZR.Admin.WebApi.Controllers.System
dict.Add("status", "success");
dict.Add("token", JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(tokenModel)));
CacheService.SetScanLogin(dto.Uuid, dict);
-
+
return SUCCESS(1);
}
return ToResponse(ResultCode.FAIL, "二维码已失效");
}
#endregion
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("checkMobile")]
+ [Log(Title = "发送短息", BusinessType = BusinessType.INSERT)]
+ public IActionResult CheckMobile([FromBody] PhoneLoginDto dto)
+ {
+ dto.LoginIP = HttpContextExtension.GetClientUserIp(HttpContext);
+
+ SysConfig sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff");
+ if (sysConfig?.ConfigValue != "off" && !SecurityCodeHelper.Validate(dto.Uuid, dto.Code, false))
+ {
+ return ToResponse(ResultCode.CUSTOM_ERROR, "验证码错误");
+ }
+ string location = HttpContextExtension.GetIpInfo(dto.LoginIP);
+ var info = sysUserService.GetFirst(f => f.Phonenumber == dto.PhoneNum) ?? throw new CustomException(ResultCode.CUSTOM_ERROR, "该手机号不存在", false);
+
+ var smsCode = RandomHelper.GenerateNum(6);
+ var smsContent = $"验证码{smsCode}(随机验证码),有效期10分钟。";
+ //TODO 发送短息验证码,1分钟内允许一次
+ smsCodeLogService.AddSmscodeLog(new ServiceCore.Model.SmsCodeLog()
+ {
+ Userid = info.UserId,
+ PhoneNum = dto.PhoneNum.ParseToLong(),
+ AddTime = DateTime.Now,
+ SendType = 1,
+ SmsCode = smsCode,
+ SmsContent = smsContent,
+ UserIP = dto.LoginIP,
+ Location = location,
+ });
+ CacheService.SetPhoneCode(dto.PhoneNum, smsCode);
+
+ return SUCCESS(new { smsCode });
+ }
+
+ ///
+ /// 手机号登录
+ ///
+ /// 登录对象
+ ///
+ [Route("PhoneLogin")]
+ [HttpPost]
+ [Log(Title = "手机号登录")]
+ public IActionResult PhoneLogin([FromBody] PhoneLoginDto loginBody)
+ {
+ if (loginBody == null) { throw new CustomException("请求参数错误"); }
+ loginBody.LoginIP = HttpContextExtension.GetClientUserIp(HttpContext);
+
+ if (!CacheService.CheckPhoneCode(loginBody.PhoneNum, loginBody.PhoneCode))
+ {
+ return ToResponse(ResultCode.CUSTOM_ERROR, "短信验证码错误");
+ }
+ var info = sysUserService.GetFirst(f => f.Phonenumber == loginBody.PhoneNum) ?? throw new CustomException(ResultCode.CUSTOM_ERROR, "该手机号不存在", false);
+ sysLoginService.CheckLockUser(info.UserName);
+ string location = HttpContextExtension.GetIpInfo(loginBody.LoginIP);
+ var user = sysLoginService.PhoneLogin(loginBody, new SysLogininfor() { LoginLocation = location }, info);
+
+ List roles = roleService.SelectUserRoleListByUserId(user.UserId);
+ //权限集合 eg *:*:*,system:user:list
+ List permissions = permissionService.GetMenuPermission(user);
+
+ TokenModel loginUser = new(user.Adapt(), roles.Adapt>());
+ CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.UserId, permissions);
+ return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser)));
+ }
}
}
diff --git a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs
index ca2738a..61304a2 100644
--- a/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs
+++ b/ZR.Admin.WebApi/Controllers/System/SysProfileController.cs
@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using ZR.Admin.WebApi.Filters;
+using ZR.Infrastructure.Helper;
using ZR.Model.System;
using ZR.Model.System.Dto;
using ZR.Service.System.IService;
diff --git a/ZR.Admin.WebApi/wwwroot/data.xlsx b/ZR.Admin.WebApi/wwwroot/data.xlsx
index 6c84d58..8fca81c 100644
Binary files a/ZR.Admin.WebApi/wwwroot/data.xlsx and b/ZR.Admin.WebApi/wwwroot/data.xlsx differ
diff --git a/ZR.ServiceCore/Model/Dto/PhoneLoginDto.cs b/ZR.ServiceCore/Model/Dto/PhoneLoginDto.cs
new file mode 100644
index 0000000..37e11ad
--- /dev/null
+++ b/ZR.ServiceCore/Model/Dto/PhoneLoginDto.cs
@@ -0,0 +1,25 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace ZR.ServiceCore.Model.Dto
+{
+ public class PhoneLoginDto
+ {
+ ///
+ /// 验证码
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// 唯一标识
+ ///
+ public string Uuid { get; set; } = "";
+ public string LoginIP { get; set; }
+ [Required(ErrorMessage = "手机号不能为空")]
+ public string PhoneNum { get; set; }
+ ///
+ /// 手机短信验证码
+ ///
+ //[Required(ErrorMessage = "短信验证码不能为空")]
+ public string PhoneCode { get; set; }
+ }
+}
diff --git a/ZR.ServiceCore/Services/CacheService.cs b/ZR.ServiceCore/Services/CacheService.cs
index 7ba1ead..7594b4f 100644
--- a/ZR.ServiceCore/Services/CacheService.cs
+++ b/ZR.ServiceCore/Services/CacheService.cs
@@ -1,11 +1,11 @@
-using System;
-using ZR.Common;
+using ZR.Common;
namespace ZR.Service.System
{
public class CacheService
{
private readonly static string CK_verifyScan = "verifyScan_";
+ private readonly static string CK_phoneSmsCode = "phone_sms_code_";
#region 用户权限 缓存
public static List GetUserPerms(string key)
{
@@ -59,5 +59,23 @@ namespace ZR.Service.System
}
return 0;
}
+
+ public static object SetPhoneCode(string key, string val)
+ {
+ var ck = CK_phoneSmsCode + key;
+
+ return CacheHelper.SetCache(ck, val, 10);
+ }
+ public static bool CheckPhoneCode(string key, string val)
+ {
+ var ck = CK_phoneSmsCode + key;
+ var save_code = CacheHelper.Get(ck);
+
+ if (save_code != null && save_code.Equals(val))
+ {
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/ZR.ServiceCore/Services/IService/ISysLoginService.cs b/ZR.ServiceCore/Services/IService/ISysLoginService.cs
index 15d6ba8..b3ac59b 100644
--- a/ZR.ServiceCore/Services/IService/ISysLoginService.cs
+++ b/ZR.ServiceCore/Services/IService/ISysLoginService.cs
@@ -1,8 +1,7 @@
-using Infrastructure;
-using System;
-using ZR.Model;
+using ZR.Model;
using ZR.Model.System;
using ZR.Model.System.Dto;
+using ZR.ServiceCore.Model.Dto;
namespace ZR.Service.System.IService
{
@@ -15,7 +14,14 @@ namespace ZR.Service.System.IService
///
///
public SysUser Login(LoginBodyDto loginBody, SysLogininfor logininfor);
-
+ ///
+ /// 手机号登录
+ ///
+ ///
+ ///
+ ///
+ ///
+ SysUser PhoneLogin(PhoneLoginDto loginBody, SysLogininfor logininfor, SysUser user);
///
/// 查询操作日志
///
diff --git a/ZR.ServiceCore/Services/IService/ISysUserService.cs b/ZR.ServiceCore/Services/IService/ISysUserService.cs
index a074e85..faf5bd1 100644
--- a/ZR.ServiceCore/Services/IService/ISysUserService.cs
+++ b/ZR.ServiceCore/Services/IService/ISysUserService.cs
@@ -81,6 +81,6 @@ namespace ZR.Service.System.IService
SysUser Login(LoginBodyDto user);
- void UpdateLoginInfo(LoginBodyDto user, long userId);
+ void UpdateLoginInfo(string userIP, long userId);
}
}
diff --git a/ZR.ServiceCore/Services/SysLoginService.cs b/ZR.ServiceCore/Services/SysLoginService.cs
index 2a3dbd7..4f4d63e 100644
--- a/ZR.ServiceCore/Services/SysLoginService.cs
+++ b/ZR.ServiceCore/Services/SysLoginService.cs
@@ -1,6 +1,5 @@
using Infrastructure;
using Infrastructure.Attribute;
-using Infrastructure.Extensions;
using Microsoft.AspNetCore.Http;
using UAParser;
using ZR.Model;
@@ -8,6 +7,7 @@ using ZR.Model.System;
using ZR.Model.System.Dto;
using ZR.Repository;
using ZR.Service.System.IService;
+using ZR.ServiceCore.Model.Dto;
namespace ZR.Service.System
{
@@ -64,10 +64,40 @@ namespace ZR.Service.System
logininfor.Status = "0";
logininfor.Msg = "登录成功";
AddLoginInfo(logininfor);
- SysUserService.UpdateLoginInfo(loginBody, user.UserId);
+ SysUserService.UpdateLoginInfo(loginBody.LoginIP, user.UserId);
return user;
}
+ ///
+ /// 登录验证
+ ///
+ ///
+ ///
+ ///
+ ///
+ public SysUser PhoneLogin(PhoneLoginDto loginBody, SysLogininfor logininfor, SysUser user)
+ {
+ logininfor.UserName = user.UserName;
+ logininfor.Status = "1";
+ logininfor.LoginTime = DateTime.Now;
+ logininfor.Ipaddr = loginBody.LoginIP;
+ ClientInfo clientInfo = httpContextAccessor.HttpContext.GetClientInfo();
+ logininfor.Browser = clientInfo.ToString();
+ logininfor.Os = clientInfo.OS.ToString();
+
+ if (user.Status == 1)
+ {
+ logininfor.Msg = "该用户已禁用";
+ AddLoginInfo(logininfor);
+ throw new CustomException(ResultCode.LOGIN_ERROR, logininfor.Msg, false);
+ }
+
+ logininfor.Status = "0";
+ logininfor.Msg = "登录成功";
+ AddLoginInfo(logininfor);
+ SysUserService.UpdateLoginInfo(loginBody.LoginIP, user.UserId);
+ return user;
+ }
///
/// 查询登录日志
///
diff --git a/ZR.ServiceCore/Services/SysUserService.cs b/ZR.ServiceCore/Services/SysUserService.cs
index 7d7a4c3..17d955d 100644
--- a/ZR.ServiceCore/Services/SysUserService.cs
+++ b/ZR.ServiceCore/Services/SysUserService.cs
@@ -329,12 +329,12 @@ namespace ZR.Service
///
/// 修改登录信息
///
- ///
+ ///
///
///
- public void UpdateLoginInfo(LoginBodyDto user, long userId)
+ public void UpdateLoginInfo(string userIP, long userId)
{
- Update(new SysUser() { LoginIP = user.LoginIP, LoginDate = DateTime.Now, UserId = userId }, it => new { it.LoginIP, it.LoginDate });
+ Update(new SysUser() { LoginIP = userIP, LoginDate = DateTime.Now, UserId = userId }, it => new { it.LoginIP, it.LoginDate });
}
}
}