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/Platform/Controllers/AccountController.cs

985 lines
38 KiB

using Infrastructure.Application.Services.Settings;
using Infrastructure.Data;
using Infrastructure.Email;
using Infrastructure.Extensions;
using Infrastructure.Security;
using Infrastructure.Sms;
using Infrastructure.Web;
using Infrastructure.Web.DataAnnotations;
using IoT.Shared.Application.Domain.Entities;
using IoT.Shared.Application.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Platform.Areas.IoTCenter.Controllers;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace Platform.Controllers
{
[Authorize]
public class AccountController : BaseController
{
private readonly IWebHostEnvironment _env;
private readonly IConfiguration _cfg;
private readonly ILogger<AccountController> _logger;
private readonly ISettingService _settingService;
private readonly IRepository<User> _userRepo;
private readonly IRepository<Site> _siteRepo;
private readonly IEncryptionService _encryptionService;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
//private readonly FaceRecognitionService _frs;
public AccountController(IWebHostEnvironment env,
IConfiguration cfg,
ILogger<AccountController> logger,
ISettingService settingService,
IRepository<User> userRepo,
IRepository<Site> siteRepo,
IEncryptionService encryptionService,
IEmailSender emaliSender,
ISmsSender smsSender,
AjaxController ajax
//FaceRecognitionService frs
)
{
this._env = env;
this._cfg = cfg;
this._logger = logger;
this._settingService = settingService;
this._userRepo = userRepo;
this._siteRepo = siteRepo;
this._encryptionService = encryptionService;
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 Result<LoginModel>(new LoginModel());
}
[AllowAnonymous]
[HttpPost]
public IActionResult LoginApi([FromBody] LoginModel model, string returnUrl = null)
{
return this.Login(model, returnUrl);
}
[AllowAnonymous]
[HttpPost]
public IActionResult Login(LoginModel model, string returnUrl = null)
{
var userName = model.UserName;
var password = model.Password;
var key = "";
var message = "";
if (ModelState.IsValid)
{
try
{
var user = this._userRepo.Table()
.Include(o => o.OrganUsers)
.ThenInclude(o => o.Organ)
.FirstOrDefault(o => o.UserName == userName);
if (user == null)
{
key = nameof(model.UserName);
message = "用户不存在";
}
else
{
var maxAccessFailedCount = Convert.ToInt32(this._settingService.GetValue("MaxFailedAccessAttemptsBeforeLockout"));
var lockoutEndMinutes = Convert.ToInt32(this._settingService.GetValue("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 mainOrgan = user.OrganUsers.FirstOrDefault(o => o.IsDefault)?.Organ ?? user.OrganUsers.OrderBy(o => o.Organ.Name).FirstOrDefault()?.Organ;
var timeout = model.RememberMe ? DateTime.Now.AddYears(1) : DateTime.Now.AddMinutes(Convert.ToDouble(_settingService.GetValue("AccessTokenTimeout")));
var token = Request.HttpContext.CreateJwtToken(new List<Claim> { new Claim(ClaimTypes.Name, userName) }, timeout);
if (this.IsJsonRequest())
{
return Json(this.CreateToken(userName));
}
else
{
HttpContext.JwtSignIn(model.UserName, model.RememberMe, mainOrgan?.Id.ToString());
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
var urls = new List<string>();
var list = this._siteRepo.ReadOnlyTable().ToList();
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():HH:mm}后重试";
}
else
{
key = nameof(model.Password);
message = "密码错误";
}
}
}
}
catch (DbUpdateException ex)
{
ex.PrintStack();
message = ex.Message;
}
}
ModelState.AddModelError(key, message);
ViewData["ReturnUrl"] = returnUrl;
return Result<LoginModel>(model);
}
#endregion 登录
#region 注册
[AllowAnonymous]
public JsonResult UserNameNotUsed([Required(ErrorMessage = nameof(RequiredAttribute))] 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 (Convert.ToBoolean(this._settingService.GetValue("RegisterDisabled")))
{
return RedirectTo("Index", "Home", "当前未开放注册");
}
if (User.Identity.IsAuthenticated)
{
return RedirectTo("Index", "Home", "当前已登录,请退出");
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
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(ErrorMessage = nameof(RequiredAttribute))] string email)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.Email == email));
}
return Json("邮箱不能为空");
}
[AllowAnonymous]
public JsonResult SendCodeToEmail([Required(ErrorMessage = nameof(RequiredAttribute))] string email)
{
if (ModelState.IsValid)
{
try
{
string code = this.GetRandomCode();
this.SendCodeToEmailInternal(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)
{
this._logger.LogError(ex.ToString());
return Json(new { success = false, data = "邮件发送失败,请稍后重试" });
}
}
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(ErrorMessage = nameof(RequiredAttribute))] string phoneNumber)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.PhoneNumber == phoneNumber));
}
return Json("邮箱不能为空");
}
[AllowAnonymous]
public JsonResult SendCodeToPhoneNumber([Required(ErrorMessage = nameof(RequiredAttribute))] 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)
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == model.UserName);
if (ModelState.IsValid)
{
if (this._userRepo.Table().Any(o => o.UserName == model.UserName))
{
this.HttpContext.Session.Remove(ResetPasswordModel.Key);
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.NewPassword, user.SecurityStamp);
this._userRepo.SaveChanges();
return RedirectTo(nameof(Login), rawMesage: "密码修改成功,请重新登录");
}
ModelState.AddModelError(nameof(model.UserName), "用户名不存在");
}
this.HttpContext.Session.Remove(ResetPasswordModel.Key);
ViewData.SelectList(o => model.Type, () => this.GetTypeList(user, model.Type));
//ModelState.Remove(nameof(model.CodeCaptcha));
return View(model);
}
[AllowAnonymous]
public JsonResult HasUser([Required(ErrorMessage = nameof(RequiredAttribute))] string userName)
{
if (ModelState.IsValid)
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.UserName == userName);
if (user != null)
{
var selectList = GetTypeList(user);
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("用户名不能为空");
}
private SelectList GetTypeList(User user, object selectedValue = null)
{
var list = new List<SelectListItem>();
if (user.EmailConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.Email, "...@", "***@"), Value = Url.Action(nameof(SendCodeToEmailForResetPassword)) });
}
var smsEnabled = Convert.ToBoolean(this._settingService.GetValue("sms"));
if (smsEnabled && user.PhoneNumberConfirmed)
{
list.Add(new SelectListItem { Text = Regex.Replace(user.PhoneNumber, "...$", "***"), Value = Url.Action(nameof(SendCodeToPhoneNumberForResetPassword)) });
}
var selectList = new SelectList(list, "Value", "Text", selectedValue);
return selectList;
}
[AllowAnonymous]
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.SendCodeToEmailInternal(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)
{
this._logger.LogError(ex.ToString());
return Json(new { success = false, data = "邮件发送失败,请稍后重试" });
}
}
return Json(new { success = false, data = "会话已过期,请刷新页面" });
}
[AllowAnonymous]
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]
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 安全验证
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.SendCodeToEmailInternal(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 });
}
}
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)) });
}
var smsEnabled = Convert.ToBoolean(this._settingService.GetValue("sms"));
if (smsEnabled && 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]
//[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")}");
}
public IActionResult ChangeOrgan(string userCurrentOrganNumber, string returnUrl)
{
this.HttpContext.JwtSignOut();
this.HttpContext.JwtSignIn(User.Identity.Name, false, userCurrentOrganNumber);
return Redirect(returnUrl);
}
#region tools
private void SendCodeToEmailInternal(string email, string code)
{
var name = this._settingService.GetValue("name");
this._emailSender.SendMail(name,
this._settingService.GetValue("email:user"),
email,
$"{name}注册验证码", $"{name} 验证码:{code}",
this._settingService.GetValue("email:host"),
Convert.ToInt32(this._settingService.GetValue("email:port")),
this._settingService.GetValue("email:user"),
this._settingService.GetValue("email:password"));
}
private string GetRandomCode(int length = 4)
{
if (this._env.IsDevelopment())
{
return "1234";
}
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 int GetCaptchaSeconds()
{
return Convert.ToInt32(this._settingService.GetValue("CaptchaSeconds"));
}
private object CreateToken(String userName)
{
return new
{
AccessToken = Request.HttpContext.CreateJwtToken(new List<Claim> { new Claim(ClaimTypes.Name, userName) }, DateTime.Now.AddMinutes(Convert.ToDouble(_settingService.GetValue("AccessTokenTimeout")))),
RefreshToken = Request.HttpContext.CreateJwtToken(new List<Claim> { new Claim(ClaimTypes.Name, userName) }, DateTime.Now.AddMinutes(Convert.ToDouble(_settingService.GetValue("RefreshTokenTimeout")))),
};
}
#endregion tools
}
}