新用户首次登录 .NET Core 时强制进行 2 因素身份验证
Force 2 Factor Authentication for new users when they login for the first time .NET Core
我正在尝试在用户首次登录 .net core 时配置 2FA。所以我添加了一个 if 条件来检查 2FA 是否未启用然后重定向到创建 MFA,但是,这里的一个主要缺陷是用户可以更改浏览器上的 URL link 以跳过 2FA 创建,我怎样才能避免这种情况?以下是我的帐户控制器代码:
登录控制器方法
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
return View();
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
returnurl ??= Url.Content("~/");
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.UserName);
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
if (user.TwoFactorEnabled==false)
{
return RedirectToAction(nameof(EnableAuthenticator), new { returnurl, model.RememberMe });
}
return LocalRedirect(returnurl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(VerifyAuthenticatorCode), new { returnurl, model.RememberMe });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
启用 2FA 控制器方法
[HttpGet]
public async Task<IActionResult> EnableAuthenticator()
{
string AuthenticatorUriFormat = "MY-OTP-SECRET-HERE";
var user = await _userManager.GetUserAsync(User);
await _userManager.ResetAuthenticatorKeyAsync(user);
var token = await _userManager.GetAuthenticatorKeyAsync(user);
string AuthenticatorUri = string.Format(AuthenticatorUriFormat, _urlEncoder.Encode("My-App-Name-Here"),
_urlEncoder.Encode(user.Email), token);
var model = new MFAViewModel() { Token = token, QRCodeUrl = AuthenticatorUri };
return View(model);
}
[HttpPost]
public async Task<IActionResult> EnableAuthenticator(MFAViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.GetUserAsync(User);
var succeeded = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code);
if (succeeded)
{
await _userManager.SetTwoFactorEnabledAsync(user, true);
}
else
{
ModelState.AddModelError("Verify", "Your two factor auth code could not be validated.");
return View(model);
}
}
return RedirectToAction(nameof(AuthenticatorConfirmation));
}
如我的评论所述,您可以考虑配置应用程序使用 Claims-based authorization,在用户使用 2FA 成功登录后,您可以添加一个声明存储 2FA 登录结果并将其添加到登录用户。之后,在您的应用程序中,创建一个需要声明的策略,并在每个控制器上添加 Authorize 属性。
此外,您还可以在 2FA 之后添加用户声明,然后创建自定义 middleware/Authorize 属性来验证每个请求并检查当前用户是否包含声明。您可以参考以下链接:Custom Authorization attributes and How To Override Attribute Class To Do Custom Authorization In .NET Core.
我正在尝试在用户首次登录 .net core 时配置 2FA。所以我添加了一个 if 条件来检查 2FA 是否未启用然后重定向到创建 MFA,但是,这里的一个主要缺陷是用户可以更改浏览器上的 URL link 以跳过 2FA 创建,我怎样才能避免这种情况?以下是我的帐户控制器代码:
登录控制器方法
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
return View();
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model, string? returnurl = null)
{
ViewData["ReturnUrl"] = returnurl;
returnurl ??= Url.Content("~/");
if (ModelState.IsValid)
{
var user = await _userManager.FindByNameAsync(model.UserName);
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
if (user.TwoFactorEnabled==false)
{
return RedirectToAction(nameof(EnableAuthenticator), new { returnurl, model.RememberMe });
}
return LocalRedirect(returnurl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(VerifyAuthenticatorCode), new { returnurl, model.RememberMe });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
return View(model);
}
启用 2FA 控制器方法
[HttpGet]
public async Task<IActionResult> EnableAuthenticator()
{
string AuthenticatorUriFormat = "MY-OTP-SECRET-HERE";
var user = await _userManager.GetUserAsync(User);
await _userManager.ResetAuthenticatorKeyAsync(user);
var token = await _userManager.GetAuthenticatorKeyAsync(user);
string AuthenticatorUri = string.Format(AuthenticatorUriFormat, _urlEncoder.Encode("My-App-Name-Here"),
_urlEncoder.Encode(user.Email), token);
var model = new MFAViewModel() { Token = token, QRCodeUrl = AuthenticatorUri };
return View(model);
}
[HttpPost]
public async Task<IActionResult> EnableAuthenticator(MFAViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.GetUserAsync(User);
var succeeded = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, model.Code);
if (succeeded)
{
await _userManager.SetTwoFactorEnabledAsync(user, true);
}
else
{
ModelState.AddModelError("Verify", "Your two factor auth code could not be validated.");
return View(model);
}
}
return RedirectToAction(nameof(AuthenticatorConfirmation));
}
如我的评论所述,您可以考虑配置应用程序使用 Claims-based authorization,在用户使用 2FA 成功登录后,您可以添加一个声明存储 2FA 登录结果并将其添加到登录用户。之后,在您的应用程序中,创建一个需要声明的策略,并在每个控制器上添加 Authorize 属性。
此外,您还可以在 2FA 之后添加用户声明,然后创建自定义 middleware/Authorize 属性来验证每个请求并检查当前用户是否包含声明。您可以参考以下链接:Custom Authorization attributes and How To Override Attribute Class To Do Custom Authorization In .NET Core.