feat: 短信验证码登陆方式增加登录日志
This commit is contained in:
parent
5c61362e57
commit
736279b7f6
|
@ -11,9 +11,11 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bootstrap.Admin.Controllers
|
namespace Bootstrap.Admin.Controllers
|
||||||
|
@ -45,10 +47,13 @@ namespace Bootstrap.Admin.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统锁屏界面
|
/// 系统锁屏界面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="ipLocator"></param>
|
||||||
|
/// <param name="userName"></param>
|
||||||
|
/// <param name="password"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[IgnoreAntiforgeryToken]
|
[IgnoreAntiforgeryToken]
|
||||||
public Task<IActionResult> Lock([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, string userName, string password) => Login(onlineUserSvr, ipLocator, userName, password, string.Empty);
|
public Task<IActionResult> Lock([FromServices]IIPLocatorProvider ipLocator, string userName, string password) => Login(ipLocator, userName, password, string.Empty);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 系统登录方法
|
/// 系统登录方法
|
||||||
|
@ -68,79 +73,75 @@ namespace Bootstrap.Admin.Controllers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 短信验证登陆方法
|
/// 短信验证登陆方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
|
||||||
/// <param name="ipLocator"></param>
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="configuration"></param>
|
/// <param name="configuration"></param>
|
||||||
/// <param name="phone"></param>
|
/// <param name="phone"></param>
|
||||||
/// <param name="code"></param>
|
/// <param name="code"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost()]
|
[HttpPost()]
|
||||||
public async Task<IActionResult> Mobile([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromServices]IConfiguration configuration, [FromQuery]string phone, [FromQuery]string code)
|
public async Task<IActionResult> Mobile([FromServices]IIPLocatorProvider ipLocator, [FromServices]IConfiguration configuration, [FromQuery]string phone, [FromQuery]string code)
|
||||||
{
|
{
|
||||||
var option = configuration.GetSection(nameof(SMSOptions)).Get<SMSOptions>();
|
var option = configuration.GetSection(nameof(SMSOptions)).Get<SMSOptions>();
|
||||||
if (UserHelper.AuthenticateMobile(phone, code, option.MD5Key, loginUser => CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
if (SMSHelper.Validate(phone, code, option.MD5Key))
|
||||||
{
|
{
|
||||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
var user = UserHelper.Retrieves().FirstOrDefault(u => u.UserName == phone);
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Name, phone));
|
if (user == null)
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Role, "Default"));
|
|
||||||
await HttpContext.SignInAsync(new ClaimsPrincipal(identity));
|
|
||||||
|
|
||||||
if (UserHelper.RetrieveUserByUserName(identity) == null)
|
|
||||||
{
|
{
|
||||||
var user = new User()
|
user = new User()
|
||||||
{
|
{
|
||||||
ApprovedBy = "Mobile",
|
ApprovedBy = "Mobile",
|
||||||
ApprovedTime = DateTime.Now,
|
ApprovedTime = DateTime.Now,
|
||||||
DisplayName = "手机用户",
|
DisplayName = "手机用户",
|
||||||
UserName = phone,
|
UserName = phone,
|
||||||
Password = LgbCryptography.GenerateSalt(),
|
Password = code,
|
||||||
Icon = "default.jpg",
|
Icon = "default.jpg",
|
||||||
Description = "手机用户",
|
Description = "手机用户",
|
||||||
App = "2"
|
App = option.App
|
||||||
};
|
};
|
||||||
UserHelper.Save(user);
|
UserHelper.Save(user);
|
||||||
CacheCleanUtility.ClearCache(cacheKey: UserHelper.RetrieveUsersDataKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
// redirect origin url
|
// 根据配置文件设置默认角色
|
||||||
var originUrl = Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].FirstOrDefault() ?? "~/Home/Index";
|
var roles = RoleHelper.Retrieves().Where(r => option.Roles.Any(rl => rl.Equals(r.RoleName, StringComparison.OrdinalIgnoreCase))).Select(r => r.Id);
|
||||||
return Redirect(originUrl);
|
RoleHelper.SaveByUserId(user.Id, roles);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// update password
|
||||||
|
UserHelper.Update(user.Id, code, user.DisplayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return View("Login", new LoginModel() { AuthFailed = true });
|
return await Login(ipLocator, phone, code, "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Login the specified userName, password and remember.
|
/// Login the specified userName, password and remember.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The login.</returns>
|
/// <returns>The login.</returns>
|
||||||
/// <param name="onlineUserSvr"></param>
|
|
||||||
/// <param name="ipLocator"></param>
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="userName">User name.</param>
|
/// <param name="userName">User name.</param>
|
||||||
/// <param name="password">Password.</param>
|
/// <param name="password">Password.</param>
|
||||||
/// <param name="remember">Remember.</param>
|
/// <param name="remember">Remember.</param>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Login([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, string userName, string password, string remember)
|
public async Task<IActionResult> Login([FromServices]IIPLocatorProvider ipLocator, string userName, string password, string remember) => UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(ipLocator, HttpContext, loginUser)) ? await SignInAsync(userName, remember == "true") : View("Login", new LoginModel() { AuthFailed = true });
|
||||||
|
|
||||||
|
private async Task<IActionResult> SignInAsync(string userName, bool persistent)
|
||||||
{
|
{
|
||||||
if (UserHelper.Authenticate(userName, password, loginUser => CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
{
|
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
|
||||||
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
|
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { ExpiresUtc = DateTimeOffset.Now.AddDays(DictHelper.RetrieveCookieExpiresPeriod()), IsPersistent = persistent });
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
|
|
||||||
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties { ExpiresUtc = DateTimeOffset.Now.AddDays(DictHelper.RetrieveCookieExpiresPeriod()), IsPersistent = remember == "true" });
|
// redirect origin url
|
||||||
// redirect origin url
|
var originUrl = Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].FirstOrDefault() ?? "~/Home/Index";
|
||||||
var originUrl = Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].FirstOrDefault() ?? "~/Home/Index";
|
return Redirect(originUrl);
|
||||||
return Redirect(originUrl);
|
|
||||||
}
|
|
||||||
return View("Login", new LoginModel() { AuthFailed = true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建登录用户信息
|
/// 创建登录用户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
|
||||||
/// <param name="ipLocator"></param>
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <param name="loginUser"></param>
|
/// <param name="loginUser"></param>
|
||||||
internal static void CreateLoginUser(IOnlineUsers onlineUserSvr, IIPLocatorProvider ipLocator, HttpContext context, LoginUser loginUser)
|
internal static void CreateLoginUser(IIPLocatorProvider ipLocator, HttpContext context, LoginUser loginUser)
|
||||||
{
|
{
|
||||||
loginUser.UserAgent = context.Request.Headers["User-Agent"];
|
loginUser.UserAgent = context.Request.Headers["User-Agent"];
|
||||||
var agent = new UserAgent(loginUser.UserAgent);
|
var agent = new UserAgent(loginUser.UserAgent);
|
||||||
|
|
|
@ -30,19 +30,18 @@ namespace Bootstrap.Admin.Controllers.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// JWT 登陆认证接口
|
/// JWT 登陆认证接口
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="onlineUserSvr"></param>
|
|
||||||
/// <param name="ipLocator"></param>
|
/// <param name="ipLocator"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public string Post([FromServices]IOnlineUsers onlineUserSvr, [FromServices]IIPLocatorProvider ipLocator, [FromBody]JObject value)
|
public string Post([FromServices]IIPLocatorProvider ipLocator, [FromBody]JObject value)
|
||||||
{
|
{
|
||||||
string token = null;
|
string token = null;
|
||||||
dynamic user = value;
|
dynamic user = value;
|
||||||
string userName = user.userName;
|
string userName = user.userName;
|
||||||
string password = user.password;
|
string password = user.password;
|
||||||
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(onlineUserSvr, ipLocator, HttpContext, loginUser)))
|
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password) && UserHelper.Authenticate(userName, password, loginUser => AccountController.CreateLoginUser(ipLocator, HttpContext, loginUser)))
|
||||||
{
|
{
|
||||||
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
|
token = BootstrapAdminJwtTokenHandler.CreateToken(userName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,9 @@
|
||||||
"SMSOptions": {
|
"SMSOptions": {
|
||||||
"CompanyCode": "<CompanyCode>",
|
"CompanyCode": "<CompanyCode>",
|
||||||
"MD5Key": "MD5Key"
|
"MD5Key": "MD5Key"
|
||||||
|
"Roles": [ "Administrators" ],
|
||||||
|
"HomePath": "/Admin/Profiles",
|
||||||
|
"App": "0"
|
||||||
},
|
},
|
||||||
"LongbowCache": {
|
"LongbowCache": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
|
|
@ -88,8 +88,11 @@
|
||||||
},
|
},
|
||||||
"SMSOptions": {
|
"SMSOptions": {
|
||||||
"CompanyCode": "<CompanyCode>",
|
"CompanyCode": "<CompanyCode>",
|
||||||
"MD5Key": "MD5Key"
|
"MD5Key": "MD5Key",
|
||||||
},
|
"Roles": [ "Default" ],
|
||||||
|
"HomePath": "/Home/Index",
|
||||||
|
"App": "2"
|
||||||
|
},
|
||||||
"LongbowCache": {
|
"LongbowCache": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
"CorsItems": [
|
"CorsItems": [
|
||||||
|
|
|
@ -6,12 +6,12 @@ using System.Collections.Generic;
|
||||||
namespace Bootstrap.DataAccess
|
namespace Bootstrap.DataAccess
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 用户登陆操作类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LoginHelper
|
public static class LoginHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
/// 记录登陆日志方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
|
@ -153,5 +153,20 @@ namespace Bootstrap.DataAccess
|
||||||
/// 获得/设置 验证码有效时长
|
/// 获得/设置 验证码有效时长
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan Expires { get; set; } = TimeSpan.FromMinutes(5);
|
public TimeSpan Expires { get; set; } = TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 角色集合
|
||||||
|
/// </summary>
|
||||||
|
public ICollection<string> Roles { get; } = new HashSet<string>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 登陆后首页
|
||||||
|
/// </summary>
|
||||||
|
public string HomePath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获得/设置 默认授权 App
|
||||||
|
/// </summary>
|
||||||
|
public string App { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace Bootstrap.DataAccess
|
||||||
{
|
{
|
||||||
if (user.Description?.Length > 500) user.Description = user.Description.Substring(0, 500);
|
if (user.Description?.Length > 500) user.Description = user.Description.Substring(0, 500);
|
||||||
if (user.UserName?.Length > 16) user.UserName = user.UserName.Substring(0, 16);
|
if (user.UserName?.Length > 16) user.UserName = user.UserName.Substring(0, 16);
|
||||||
if (user.Password?.Length > 16) user.Password = user.Password.Substring(0, 16);
|
if (user.Password?.Length > 50) user.Password = user.Password.Substring(0, 50);
|
||||||
if (user.DisplayName?.Length > 20) user.DisplayName = user.DisplayName.Substring(0, 20);
|
if (user.DisplayName?.Length > 20) user.DisplayName = user.DisplayName.Substring(0, 20);
|
||||||
var pattern = @"^[a-zA-Z0-9_@.]*$";
|
var pattern = @"^[a-zA-Z0-9_@.]*$";
|
||||||
return user.UserName.IsNullOrEmpty() || Regex.IsMatch(user.UserName, pattern);
|
return user.UserName.IsNullOrEmpty() || Regex.IsMatch(user.UserName, pattern);
|
||||||
|
@ -76,29 +76,6 @@ namespace Bootstrap.DataAccess
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 短信验证码认证方法
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="phone"></param>
|
|
||||||
/// <param name="code"></param>
|
|
||||||
/// <param name="secret"></param>
|
|
||||||
/// <param name="configure"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static bool AuthenticateMobile(string phone, string code, string secret, Action<LoginUser> configure)
|
|
||||||
{
|
|
||||||
var loginUser = new LoginUser
|
|
||||||
{
|
|
||||||
UserName = phone,
|
|
||||||
LoginTime = DateTime.Now,
|
|
||||||
Result = "登录失败"
|
|
||||||
};
|
|
||||||
configure(loginUser);
|
|
||||||
var ret = string.IsNullOrEmpty(phone) ? false : SMSHelper.Validate(phone, code, secret);
|
|
||||||
if (ret) loginUser.Result = "登录成功";
|
|
||||||
LoginHelper.Log(loginUser);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询所有的新注册用户
|
/// 查询所有的新注册用户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -149,7 +126,7 @@ namespace Bootstrap.DataAccess
|
||||||
if (DictHelper.RetrieveSystemModel() && !string.IsNullOrEmpty(user.Id) && RetrieveConstUsers().Any(u => u.Id == user.Id)) return true;
|
if (DictHelper.RetrieveSystemModel() && !string.IsNullOrEmpty(user.Id) && RetrieveConstUsers().Any(u => u.Id == user.Id)) return true;
|
||||||
|
|
||||||
var ret = DbContextManager.Create<User>().Save(user);
|
var ret = DbContextManager.Create<User>().Save(user);
|
||||||
if (ret) CacheCleanUtility.ClearCache(userIds: string.IsNullOrEmpty(user.Id) ? new List<string>() : new List<string>() { user.Id }, cacheKey: $"{RetrieveUsersByNameDataKey}*");
|
if (ret) CacheCleanUtility.ClearCache(userIds: string.IsNullOrEmpty(user.Id) ? new List<string>() : new List<string>() { user.Id }, cacheKey: $"{RetrieveUsersByNameDataKey}-{user.UserName}");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue