You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iot/projects/UserCenter/Controllers/AccountController.cs

974 lines
37 KiB

using Application.Domain.Entities;
using Application.Models;
using Infrastructure.Data;
using Infrastructure.Email;
using Infrastructure.Extensions;
using Infrastructure.Jwt;
using Infrastructure.Resources;
using Infrastructure.Security;
using Infrastructure.Sms;
using Infrastructure.Web;
using Infrastructure.Web.DataAnnotations;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using UserCenter.Services;
namespace UserCenter.Controllers
{
[Authorize]
public class AccountController : BaseController
{
private readonly IConfiguration _cfg;
private readonly IJwtHelper _jwtHelper;
private readonly IRepository<User> _userRepo;
private readonly IRepository<Site> _siteRepo;
private readonly IStringLocalizer<Resource> _localizer;
private readonly IEncryptionService _encryptionService;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly FaceRecognitionService _frs;
public AccountController(IConfiguration cfg,
IJwtHelper jwtHelper,
IRepository<User> userRepo,
IRepository<Site> siteRepo,
IEncryptionService encryptionService,
IStringLocalizer<Resource> localizer,
IEmailSender emaliSender,
ISmsSender smsSender,
FaceRecognitionService frs)
{
this._cfg = cfg;
this._jwtHelper = jwtHelper;
this._userRepo = userRepo;
this._siteRepo = siteRepo;
this._encryptionService = encryptionService;
this._localizer = localizer;
this._emailSender = emaliSender;
this._smsSender = smsSender;
this._frs = frs;
}
#region 用户中心
public IActionResult Index()
{
return View(this._siteRepo.ReadOnlyTable().ToList());
}
#endregion 用户中心
#region 注销
public IActionResult Logout(string returnUrl = null)
{
var username = User.Identity.Name;
var urls = new List<string>();
var list = this._siteRepo.ReadOnlyTable().ToList();
foreach (var site in list)
{
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var sign = string.Concat(username, timestamp, site.Key).Md5();
var url = site.Logout
.SetParam(nameof(username), username)
.SetParam(nameof(timestamp), timestamp)
.SetParam(nameof(sign), sign);
urls.Add(url);
}
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
HttpContext.JwtSignOut();
return View("JsonpLogout", urls);
}
#endregion 注销
#region 登录
[AllowAnonymous]
[HttpGet]
public IActionResult Login(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[AllowAnonymous]
[HttpPost]
public IActionResult Login(LoginModel model, string returnUrl = null)
{
return this.LoginInternal(model, false, returnUrl);
}
[AllowAnonymous]
public IActionResult GetUserInfo(string token)
{
var userName = this._jwtHelper.GetPayload(token)["UserName"].ToString();
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
return Json(new
{
Name = this._cfg["Name"],
user.Avatar,
user.UserName,
user.NickName
});
}
[AllowAnonymous]
public IActionResult LoginInternal(LoginModel model, bool isAppLogin, string returnUrl = null)
{
var userName = model.UserName;
var password = model.Password;
var key = "";
var message = "";
if (ModelState.IsValid)
{
try
{
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
if (user == null)
{
key = nameof(model.UserName);
message = "用户不存在";
}
else
{
var maxAccessFailedCount = this._cfg.GetValue<int>("MaxFailedAccessAttemptsBeforeLockout");
var lockoutEndMinutes = this._cfg.GetValue<int>("DefaultAccountLockoutMinutes");
if (user.LockoutEnabled)//对已启用登录锁定的用户,如果当前登录时间超出锁定时间,先解除锁定状态
{
if (user.LockoutEnd.HasValue && DateTime.UtcNow > user.LockoutEnd)
{
user.LockoutEnd = null;
user.AccessFailedCount = 0;
this._userRepo.SaveChanges();
}
}
var success = false;
if (user.LockoutEnabled)//对启用登录锁定的用户进行验证
{
if (user.LockoutEnd.HasValue == false)
{
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(password, user.SecurityStamp))
{
user.LockoutEnd = null;
user.AccessFailedCount = 0;
success = true;
}
else
{
user.AccessFailedCount += 1;
if (user.AccessFailedCount >= maxAccessFailedCount)
{
user.LockoutEnd = DateTime.UtcNow.AddMinutes(lockoutEndMinutes);
}
}
this._userRepo.SaveChanges();
}
}
else//对未启用登录锁定的用户进行验证
{
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(password, user.SecurityStamp))
{
success = true;
}
}
if (success)
{
var list = this._siteRepo.ReadOnlyTable().ToList();
if (isAppLogin)
{
return Json(new
{
Code = 0,
Token = this._jwtHelper.GetToken(new Dictionary<string, object>() { { nameof(user.UserName), user.UserName } })
});
}
else
{
HttpContext.JwtSignIn(model.UserName, model.RememberMe, _cfg);
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
var urls = new List<string>();
foreach (var site in list)
{
var username = user.UserName;
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var sign = string.Concat(userName, timestamp, site.Key).Md5();
var url = site.Login
.SetParam(nameof(username), username)
.SetParam(nameof(user.NickName), user.NickName)
.SetParam(nameof(user.Avatar), user.Avatar)
.SetParam(nameof(timestamp), timestamp)
.SetParam("rememberme", model.RememberMe)
.SetParam(nameof(sign), sign);
urls.Add(url);
}
Response.Headers.Remove("Location");
return View("JsonpLogin", urls);
}
}
else
{
if (user.LockoutEnabled && user.LockoutEnd.HasValue)
{
key = nameof(model.UserName);
message = $"用户被锁定,请于{user.LockoutEnd.Value.ToLocalTime().ToString("HH:mm")}后重试";
}
else
{
key = nameof(model.Password);
message = "密码错误";
}
}
}
}
catch (DbUpdateException ex)
{
ex.PrintStack();
message = ex.Message;
}
}
if (isAppLogin)
{
return Json(new { Code = 1, Key = key, Message = message });
}
else
{
ModelState.AddModelError(key, message);
ViewData["ReturnUrl"] = returnUrl;
return View(model);
}
}
#endregion 登录
#region 注册
[AllowAnonymous]
public JsonResult UserNameNotUsed([Required]string userName)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.UserName == userName));
}
return Json("用户名不能为空");
}
#endregion 注册
#region 邮箱注册
[AllowAnonymous]
public IActionResult Register(string returnUrl = null)
{
if (this.RegisterDisabled())
{
return RedirectTo("Index", "Home", "当前未开放注册");
}
if (User.Identity.IsAuthenticated)
{
return RedirectTo("Index", "Home", "当前已登录,请退出");
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public IActionResult Register(RegisterModel model, string returnUrl = null)
{
if (this._cfg.GetValue<bool>("RegisterDisabled"))
{
return RedirectTo("Index", "Home", "当前未开放注册");
}
if (ModelState.IsValid)
{
try
{
var user = new User().From(model);
user.SecurityStamp = this._encryptionService.CreateSalt();
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp);
user.PasswordConfirmed = true;
user.EmailConfirmed = true;
this._userRepo.Add(user);
this._userRepo.SaveChanges();
if (returnUrl == null)
{
returnUrl = Url.Action("Index", "Home");
}
return RedirectTo("Login", "Account", "注册成功", new { returnUrl });
}
catch (Exception ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
return View(model);
}
[AllowAnonymous]
public JsonResult EmailNotUsed([Required]string email)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.Email == email));
}
return Json("邮箱不能为空");
}
[AllowAnonymous]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToEmail([Required]string email)
{
if (ModelState.IsValid)
{
try
{
string code = this.GetRandomCode();
this.SendCodeToEmail(email, code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
return Json(new { success = false, data = "邮箱不能为空" });
}
#endregion 邮箱注册
#region 手机号注册
[AllowAnonymous]
public IActionResult RegisterByPhoneNumber(string returnUrl = null)
{
if (this._cfg.GetValue<bool>("RegisterDisabled"))
{
return RedirectTo("Index", "Home", "当前未开放注册");
}
if (User.Identity.IsAuthenticated)
{
return RedirectTo("Index", "Home", "当前已登录,请退出后再注册");
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult RegisterByPhoneNumber(RegisterPhoneNumberModel model, string returnUrl = null)
{
if (this._cfg.GetValue<bool>("RegisterDisabled"))
{
return RedirectTo("Index", "Home", "当前未开放注册");
}
if (ModelState.IsValid)
{
try
{
var user = new User().From(model);
user.SecurityStamp = this._encryptionService.CreateSalt();
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp);
user.PasswordConfirmed = true;
user.PhoneNumberConfirmed = true;
this._userRepo.Add(user);
this._userRepo.SaveChanges();
if (returnUrl == null)
{
returnUrl = Url.Action("Index", "Home");
}
return RedirectTo("Login", "Account", "注册成功", new { returnUrl });
}
catch (DbUpdateException ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
return View(model);
}
[AllowAnonymous]
public JsonResult PhoneNumberNotUsed([Required]string phoneNumber)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.PhoneNumber == phoneNumber));
}
return Json("邮箱不能为空");
}
[AllowAnonymous]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToPhoneNumber([Required]string phoneNumber)
{
if (ModelState.IsValid)
{
try
{
this._smsSender.Send(phoneNumber, out string code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
return Json(new { success = false, data = "手机号不能为空" });
}
#endregion 手机号注册
#region 重设密码
[AllowAnonymous]
public IActionResult ForgotPassword()
{
if (User.Identity.IsAuthenticated)
{
return RedirectTo("Index", "Home", "当前已登录,请退出后重试");
}
return View();
}
[HttpPost]
[AllowAnonymous]
public IActionResult ForgotPassword(ResetPasswordModel model)
{
if (ModelState.IsValid)
{
if (this._userRepo.ReadOnlyTable().Any(o => o.UserName == model.UserName))
{
this.HttpContext.Session.Remove(ResetPasswordModel.Key);
return RedirectTo(nameof(Login), rawMesage: "密码修改成功,请重新登录");
}
ModelState.AddModelError(nameof(model.UserName), "用户名不存在");
}
this.HttpContext.Session.Remove(ResetPasswordModel.Key);
return RedirectTo(nameof(ForgotPassword), rawMesage: "请重试");
}
[AllowAnonymous]
public JsonResult HasUser([Required]string userName)
{
if (ModelState.IsValid)
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (user != null)
{
var list = new List<SelectListItem>();
if (user.EmailConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.Email, "...@", "***@"), Value = Url.Action(nameof(SendCodeToEmailForResetPassword)) });
}
if (user.PhoneNumberConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.PhoneNumber, "...$", "***"), Value = Url.Action(nameof(SendCodeToPhoneNumberForResetPassword)) });
}
var selectList = new SelectList(list, "Value", "Text");
HttpContext.Response.Headers.Add("x-model", JsonConvert.SerializeObject(selectList));
HttpContext.Session.Set(ResetPasswordModel.Key, new ResetPasswordModel { UserName = userName });
HttpContext.Session.Remove(CodeCaptchaModel.Key);
return Json(true);
}
return Json("用户名不存在");
}
return Json("用户名不能为空");
}
[AllowAnonymous]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToEmailForResetPassword()
{
var model = HttpContext.Session.Get<ResetPasswordModel>(ResetPasswordModel.Key);
if (model != null)
{
try
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == model.UserName);
var email = user.Email;
string code = this.GetRandomCode();
this.SendCodeToEmail(email, code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
return Json(new { success = false, data = "会话已过期,请刷新页面" });
}
[AllowAnonymous]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToPhoneNumberForResetPassword()
{
var model = HttpContext.Session.Get<ResetPasswordModel>(ResetPasswordModel.Key);
if (model == null)
{
try
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == model.UserName);
var phoneNumber = user.PhoneNumber;
this._smsSender.Send(phoneNumber, out string code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
return Json(new { success = false, data = "会话已过期,请刷新页面" });
}
#endregion 重设密码
#region 修改密码
public IActionResult ChangePassword()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
try
{
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == User.Identity.Name);
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(model.OldPassword, user.SecurityStamp))
{
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.NewPassword, user.SecurityStamp);
this._userRepo.SaveChanges();
return RedirectTo(rawMesage: "密码修改成功");
}
else
{
ModelState.AddModelError(nameof(model.OldPassword), "当前密码输入错误");
}
}
catch (DbUpdateException ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
return View(model);
}
#endregion 修改密码
#region 用户信息
public IActionResult UserInfo()
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == User.Identity.Name);
var model = user.To<EditUserInfoModel>();
return View(model);
}
[HttpPost]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public IActionResult UserInfo(EditUserInfoModel model)
{
try
{
var usreName = User.Identity.Name;
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == usreName);
user.From(model);
this._userRepo.SaveChanges();
return RedirectTo(rawMesage: "基本信息修改成功");
}
catch (Exception ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
return View(model);
}
#endregion 用户信息
#region 账户安全
public IActionResult Security()
{
return View(this._userRepo.Table().FirstOrDefault(o => o.UserName == User.Identity.Name));
}
#endregion 账户安全
#region 设置修改邮箱
public IActionResult SetEmail()
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
return Validate(user);
}
[HttpPost]
public IActionResult SetEmail(ValidateModel model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
ViewData["HtmlAction"] = Url.Action("SetEmail2");
return View();
}
return RedirectTo("ChangeEmail", rawMesage: "请重试");
}
[HttpPost]
public IActionResult SetEmail2(ChangeEmailModel model)
{
if (ModelState.IsValid)
{
var userName = User.Identity.Name;
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
user.Email = model.Email;
user.EmailConfirmed = true;
this._userRepo.SaveChanges();
return RedirectTo("Security", rawMesage: "设置邮箱成功");
}
return RedirectTo("ChangeEmail", rawMesage: "请重试");
}
public IActionResult ChangeEmail()
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (!user.EmailConfirmed)
{
return RedirectTo("SetEmail", rawMesage: "尚未设置邮箱");
}
return Validate(user);
}
[HttpPost]
public IActionResult ChangeEmail(ValidateModel model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
ViewData["HtmlAction"] = Url.Action("ChangeEmail2");
return View();
}
return RedirectTo("ChangeEmail", rawMesage: "请重试");
}
[HttpPost]
public IActionResult ChangeEmail2(ChangeEmailModel model)
{
if (ModelState.IsValid)
{
var userName = User.Identity.Name;
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
user.Email = model.Email;
this._userRepo.SaveChanges();
return RedirectTo("Security", rawMesage: "更换邮箱成功");
}
return RedirectTo("ChangeEmail", rawMesage: "请重试");
}
#endregion 设置修改邮箱
#region 设置修改手机号
public IActionResult SetPhoneNumber()
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
return Validate(user);
}
[HttpPost]
public IActionResult SetPhoneNumber(ValidateModel model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
ViewData["HtmlAction"] = Url.Action("SetPhoneNumber2");
return View();
}
return RedirectTo("ChangePhoneNumber", rawMesage: "请重试");
}
[HttpPost]
public IActionResult SetPhoneNumber2(ChangePhoneNumberModel model)
{
if (ModelState.IsValid)
{
var userName = User.Identity.Name;
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
user.PhoneNumber = model.PhoneNumber;
user.PhoneNumberConfirmed = true;
this._userRepo.SaveChanges();
return RedirectTo("Security", rawMesage: "设置手机号成功");
}
return RedirectTo("ChangePhoneNumber", rawMesage: "请重试");
}
public IActionResult ChangePhoneNumber()
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (!user.PhoneNumberConfirmed)
{
return RedirectTo("SetPhoneNumber", rawMesage: "尚未设置手机号");
}
return Validate(user);
}
[HttpPost]
public IActionResult ChangePhoneNumber(ValidateModel model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
ViewData["HtmlAction"] = Url.Action("ChangePhoneNumber2");
return View();
}
return RedirectTo("ChangePhoneNumber", rawMesage: "请重试");
}
[HttpPost]
public IActionResult ChangePhoneNumber2(ChangePhoneNumberModel model)
{
if (ModelState.IsValid)
{
var userName = User.Identity.Name;
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
user.PhoneNumber = model.PhoneNumber;
this._userRepo.SaveChanges();
return RedirectTo("Security", rawMesage: "更换手机号成功");
}
return RedirectTo("ChangePhoneNumber", rawMesage: "请重试");
}
#endregion 设置修改手机号
#region 安全验证
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToEmailForValid()
{
try
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
var email = user.Email;
string code = this.GetRandomCode();
this.SendCodeToEmail(email, code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
public JsonResult SendCodeToPhoneNumberForValid()
{
try
{
var userName = User.Identity.Name;
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
var phoneNumber = user.PhoneNumber;
this._smsSender.Send(phoneNumber, out string code);
var seconds = this.GetCaptchaSeconds();
this.HttpContext.Session.Set(CodeCaptchaModel.Key, new CodeCaptchaModel
{
ExpireDateUtc = DateTime.UtcNow.AddSeconds(seconds),
MaxErrorLimit = 5,
Captcha = code
});
return Json(new { success = true, data = seconds });
}
catch (Exception ex)
{
ex.PrintStack();
return Json(new { success = false, data = ex.Message });
}
}
private IActionResult Validate(User user)
{
var list = new List<SelectListItem>();
if (user.EmailConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.Email, "...@", "***@"), Value = Url.Action(nameof(SendCodeToEmailForValid)) });
}
if (user.PhoneNumberConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.PhoneNumber, "...$", "***"), Value = Url.Action(nameof(SendCodeToPhoneNumberForValid)) });
}
var selectList = new SelectList(list, "Value", "Text");
ViewData["TypeSelectList"] = selectList;
return View("Validate");
}
#endregion 安全验证
#region 权限不足
[AllowAnonymous]
public IActionResult AccessDenied(string returnUrl)
{
return View(model: returnUrl);
}
#endregion 权限不足
[AllowAnonymous]
public IActionResult ServerValid()
{
return Json(new
{
Name = this._cfg["name"],
Version = this._cfg["version"]
});
}
[AllowAnonymous]
public IActionResult AppLogin(LoginModel model)
{
return this.LoginInternal(model, true);
}
[AllowAnonymous]
[HttpPost]
public IActionResult FaceLogin(IFormFile face)
{
using var stream = face.OpenReadStream();
using var bitmap = new System.Drawing.Bitmap(stream);
Console.WriteLine($"face length:{face.Length}");
var userName = this._frs.FindFace(bitmap);
if (!string.IsNullOrEmpty(userName))
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (user != null)
{
var list = this._siteRepo.ReadOnlyTable().ToList();
var result = new
{
Code = 0,
Token = this._jwtHelper.GetToken(new Dictionary<string, object>() { { nameof(user.UserName), user.UserName } })
};
return Json(result);
}
}
return Json(new { Code = 1 });
}
[AllowAnonymous]
public IActionResult HasLogin()
{
Response.Headers["Content-Type"] = "application/javascript";
return Content($"var hasLogin={(User.Identity.IsAuthenticated ? "true" : "false")}");
}
#region tools
private void SendCodeToEmail(string email, string code)
{
this._emailSender.SendMail(this._cfg["Name"], this._cfg["EmailUser"], email, $"{ this._cfg["Name"]}注册验证码", $"{this._cfg["Name"]} 验证码:{code}", this._cfg["EmailHost"], this._cfg.GetValue<int>("EmailPort"), this._cfg["EmailUser"], this._cfg["EmailPassword"]);
}
private string GetRandomCode(int length = 4)
{
var builder = new StringBuilder();
for (int i = 0; i < length; i++)
{
var random = new byte[1];
using var rg = RandomNumberGenerator.Create();
rg.GetBytes(random);
builder.Append(new Random(Convert.ToInt32(random[0])).Next(0, 9));
}
return builder.ToString();
}
private bool RegisterDisabled()
{
return this._cfg.GetValue<bool>("RegisterDisabled");
}
private int GetCaptchaSeconds()
{
return this._cfg.GetValue<int>("CaptchaSeconds");
}
#endregion tools
}
}