Dvoufaktorové ověřování pomocí SMS a e-mailu s ASP.NET Identity
Hao Kung, Pranav Rastogi, Rick Anderson, Suhas Joshi
V tomto kurzu se dozvíte, jak nastavit dvojúrovňové ověřování (2FA) pomocí SMS a e-mailu.
Tento článek napsali Rick Anderson (@RickAndMSFT), Pranav Rastogi (@rustd), Hao Kung a Suhas Joshi. Ukázku NuGet napsal primárně Hao Kung.
Toto téma se zabývá následujícími tématy:
- Vytvoření ukázky identity
- Nastavení sms pro dvojúrovňové ověřování
- Povolení dvojúrovňového ověřování
- Postup registrace zprostředkovatele dvojúrovňového ověřování
- Kombinování sociálních a místních přihlašovacích účtů
- Uzamčení účtu před útoky hrubou silou
Vytvoření ukázky identity
V této části použijete NuGet ke stažení ukázky, se kterou budeme pracovat. Začněte instalací a spuštěním Visual Studio Express 2013 pro web nebo Visual Studio 2013. Nainstalujte visual Studio 2013 Update 2 nebo novější.
Poznámka
Upozornění: K dokončení tohoto kurzu musíte nainstalovat Visual Studio 2013 Update 2 .
Vytvořte nový prázdný ASP.NET webový projekt.
V konzole Správce balíčků zadejte následující příkazy:
Install-Package SendGrid
Install-Package -Prerelease Microsoft.AspNet.Identity.Samples
V tomto kurzu použijeme SendGrid k odesílání e-mailů a Twilio nebo ASPSMS pro sms zprávy. Balíček
Identity.Samples
nainstaluje kód, se kterým budeme pracovat.Nastavte projekt tak, aby používal SSL.
Volitelné: Postupujte podle pokynů v kurzu potvrzení Email a připojte SendGrid, spusťte aplikaci a zaregistrujte e-mailový účet.
Volitelné: Odeberte z ukázky potvrzovací kód odkazu na ukázkový e-mail (Kód
ViewBag.Link
v kontroleru účtu.DisplayEmail
Viz metody akcí aForgotPasswordConfirmation
a zobrazení razor ).Volitelné:
ViewBag.Status
Odeberte kód z řadičů Manage a Account a ze zobrazení Razor Views\Account\VerifyCode.cshtml a Views\Manage\VerifyPhoneNumber.cshtml . Případně si můžete nechatViewBag.Status
displej a otestovat, jak tato aplikace funguje místně, aniž byste se museli připojovat a posílat e-maily a SMS zprávy.
Poznámka
Upozornění: Pokud změníte některé z nastavení zabezpečení v této ukázce, produkční aplikace budou muset projít auditem zabezpečení, který explicitně vyvolá provedené změny.
Nastavení sms pro dvojúrovňové ověřování
Tento kurz obsahuje pokyny pro použití Twilia nebo ASPSMS, ale můžete použít libovolného jiného poskytovatele serveru SMS.
Vytvoření uživatelského účtu u poskytovatele serveru SMS
Instalace dalších balíčků nebo přidání odkazů na služby
Twilio:
V konzole Správce balíčků zadejte následující příkaz:
Install-Package Twilio
ASPSMS:
Je potřeba přidat následující odkaz na službu:Address:
https://webservice.aspsms.com/aspsmsx2.asmx?WSDL
Obor názvů:
ASPSMSX2
Zjištění přihlašovacích údajů uživatele poskytovatele SERVERU SMS
Twilio:
Na kartě Řídicí panel účtu Twilio zkopírujte IDENTIFIKÁTOR SID účtu a token ověřování.ASPSMS:
V nastavení účtu přejděte na Userkey (Klíč uživatele ) a zkopírujte ho společně s vlastním definovaným heslem.Později tyto hodnoty uložíme do proměnných
SMSAccountIdentification
aSMSAccountPassword
.Určení SenderID / Původce
Twilio:
Na kartě Čísla zkopírujte svoje telefonní číslo Twilio.ASPSMS:
V nabídce Odemknout původce odemkněte jednoho nebo více původců nebo zvolte alfanumerický původce (nepodporuje ho všechny sítě).Později tuto hodnotu uložíme do proměnné
SMSAccountFrom
.Přenos přihlašovacích údajů poskytovatele SMS do aplikace
Zpřístupněte aplikaci přihlašovací údaje a telefonní číslo odesílatele:
public static class Keys { public static string SMSAccountIdentification = "My Idenfitication"; public static string SMSAccountPassword = "My Password"; public static string SMSAccountFrom = "+15555551234"; }
Upozornění
Zabezpečení – nikdy neukládejte citlivá data ve zdrojovém kódu. Účet a přihlašovací údaje se přidají do výše uvedeného kódu, aby byla ukázka jednoduchá. Viz ASP.NET MVC od Jona Attena : Zachování privátních nastavení mimo správu zdrojového kódu.
Implementace přenosu dat k poskytovateli serveru SMS
SmsService
Nakonfigurujte třídu v souboru App_Start\IdentityConfig.cs.V závislosti na použitém poskytovateli serveru SMS aktivujte část Twilio nebo ASPSMS :
public class SmsService : IIdentityMessageService { public Task SendAsync(IdentityMessage message) { // Twilio Begin // var Twilio = new TwilioRestClient( // Keys.SMSAccountIdentification, // Keys.SMSAccountPassword); // var result = Twilio.SendMessage( // Keys.SMSAccountFrom, // message.Destination, message.Body // ); // Status is one of Queued, Sending, Sent, Failed or null if the number is not valid // Trace.TraceInformation(result.Status); // Twilio doesn't currently have an async API, so return success. // return Task.FromResult(0); // Twilio End // ASPSMS Begin // var soapSms = new WebApplication1.ASPSMSX2.ASPSMSX2SoapClient("ASPSMSX2Soap"); // soapSms.SendSimpleTextSMS( // Keys.SMSAccountIdentification, // Keys.SMSAccountPassword, // message.Destination, // Keys.SMSAccountFrom, // message.Body); // soapSms.Close(); // return Task.FromResult(0); // ASPSMS End } }
Spusťte aplikaci a přihlaste se pomocí účtu, který jste předtím zaregistrovali.
Klikněte na id uživatele, čímž se aktivuje
Index
metoda akce vManage
kontroleru.Klikněte na Přidat.
Za několik sekund dostanete textovou zprávu s ověřovacím kódem. Zadejte ho a stiskněte Odeslat.
Zobrazení Spravovat zobrazuje, že vaše telefonní číslo bylo přidáno.
Kontrola kódu
// GET: /Account/Index
public async Task<ActionResult> Index(ManageMessageId? message)
{
ViewBag.StatusMessage =
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
: message == ManageMessageId.SetTwoFactorSuccess ? "Your two factor provider has been set."
: message == ManageMessageId.Error ? "An error has occurred."
: message == ManageMessageId.AddPhoneSuccess ? "The phone number was added."
: message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
: "";
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(User.Identity.GetUserId()),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(User.Identity.GetUserId()),
Logins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(User.Identity.GetUserId())
};
return View(model);
}
Metoda Index
akce v Manage
kontroleru nastaví stavovou zprávu na základě předchozí akce a poskytuje odkazy na změnu místního hesla nebo přidání místního účtu. Metoda Index
také zobrazí stav nebo vaše telefonní číslo 2FA, externí přihlášení, povolené 2FA a zapamatuje si metodu 2FA pro tento prohlížeč (vysvětlení dále). Kliknutím na ID uživatele (e-mail) v záhlaví se zpráva nepředá. Kliknutím na telefonní číslo: odebrat odkaz se předá Message=RemovePhoneSuccess
jako řetězec dotazu.
https://localhost:44300/Manage?Message=RemovePhoneSuccess
[]
Metoda AddPhoneNumber
akce zobrazí dialogové okno pro zadání telefonního čísla, které může přijímat zprávy SMS.
// GET: /Account/AddPhoneNumber
public ActionResult AddPhoneNumber()
{
return View();
}
Kliknutím na tlačítko Odeslat ověřovací kód odešlete telefonní číslo do metody akce HTTP POST AddPhoneNumber
.
// POST: /Account/AddPhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddPhoneNumber(AddPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Generate the token
var code = await UserManager.GenerateChangePhoneNumberTokenAsync(
User.Identity.GetUserId(), model.Number);
if (UserManager.SmsService != null)
{
var message = new IdentityMessage
{
Destination = model.Number,
Body = "Your security code is: " + code
};
// Send token
await UserManager.SmsService.SendAsync(message);
}
return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number });
}
Metoda GenerateChangePhoneNumberTokenAsync
vygeneruje token zabezpečení, který se nastaví ve zprávě SMS. Pokud je služba SMS nakonfigurovaná, token se odešle jako řetězec "Váš bezpečnostní kód je <token>". Metoda SmsService.SendAsync
pro se volá asynchronně, aplikace se pak přesměruje na metodu VerifyPhoneNumber
akce (která zobrazí následující dialogové okno), kde můžete zadat ověřovací kód.
Jakmile kód zadáte a kliknete na odeslat, odešle se do metody akce HTTP POST VerifyPhoneNumber
.
// POST: /Account/VerifyPhoneNumber
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess });
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "Failed to verify phone");
return View(model);
}
Metoda ChangePhoneNumberAsync
zkontroluje zaúčtované bezpečnostní kódy. Pokud je kód správný, telefonní číslo se přidá do PhoneNumber
pole AspNetUsers
tabulky. Pokud je toto volání úspěšné, volá se SignInAsync
metoda:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
// Clear the temporary cookies used for external and two factor sign ins
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie,
DefaultAuthenticationTypes.TwoFactorCookie);
AuthenticationManager.SignIn(new AuthenticationProperties
{
IsPersistent = isPersistent
},
await user.GenerateUserIdentityAsync(UserManager));
}
Parametr isPersistent
nastaví, jestli je relace ověřování trvalá ve více požadavcích.
Při změně profilu zabezpečení se vygeneruje nové razítko zabezpečení a uloží se do SecurityStamp
pole tabulky AspNetUsers . Všimněte si, že pole SecurityStamp
se liší od souboru cookie zabezpečení. Soubor cookie zabezpečení se neukládá do AspNetUsers
tabulky (ani nikde jinde v databázi identit). Token souboru cookie zabezpečení je podepsaný svým držitelem pomocí rozhraní DPAPI a vytvoří se s informacemi UserId, SecurityStamp
o době vypršení platnosti a .
Middleware souborů cookie kontroluje soubor cookie u každého požadavku. Metoda SecurityStampValidator
ve Startup
třídě narazí na databázi a pravidelně kontroluje razítko zabezpečení, jak je uvedeno v parametru validateInterval
. K tomu dochází pouze každých 30 minut (v naší ukázce), pokud nezměníte svůj bezpečnostní profil. 30minutový interval byl zvolen, aby se minimalizovaly cesty do databáze.
Metodu SignInAsync
je potřeba volat při jakékoli změně profilu zabezpečení. Když se změní profil zabezpečení, databáze aktualizuje SecurityStamp
pole a bez volání SignInAsync
metody byste zůstali přihlášeni pouze do chvíle, kdy kanál OWIN narazí na databázi ().validateInterval
Můžete to otestovat tak, že změníte metodu SignInAsync
tak, aby se vracela okamžitě, a nastavením vlastnosti cookie validateInterval
z 30 minut na 5 sekund:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
return;
// Clear any partial cookies from external or two factor partial sign ins
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie,
DefaultAuthenticationTypes.TwoFactorCookie);
AuthenticationManager.SignIn(new AuthenticationProperties
{
IsPersistent = isPersistent
},
await user.GenerateUserIdentityAsync(UserManager));
}
public void ConfigureAuth(IAppBuilder app) {
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a
// third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider {
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add
// an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
//validateInterval: TimeSpan.FromMinutes(30),
validateInterval: TimeSpan.FromSeconds(5),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
Pomocí výše uvedených změn kódu můžete změnit svůj profil zabezpečení (například změnou stavu Dvoufaktorové povolené) a budete odhlášeni za 5 sekund, když SecurityStampValidator.OnValidateIdentity
metoda selže. Odeberte návratový řádek v SignInAsync
metodě, proveďte další změnu profilu zabezpečení a nebudete odhlášeni. Metoda SignInAsync
vygeneruje nový soubor cookie zabezpečení.
Povolení dvoufaktorového ověřování
V ukázkové aplikaci musíte k povolení dvoufaktorového ověřování (2FA) použít uživatelské rozhraní. Pokud chcete povolit 2FA, klikněte na id uživatele (e-mailový alias) na navigačním panelu.
Klikněte na povolit 2FA.
Odhlaste se a pak se znovu přihlaste. Pokud jste povolili e-mail (viz můj předchozí kurz), můžete vybrat SMS nebo e-mail pro 2FA.
Zobrazí se stránka Ověřit kód, na které můžete kód zadat (z SMS nebo e-mailu).
Když kliknete na zaškrtávací políčko Pamatovat si tento prohlížeč , nebudete muset k přihlášení k tomuto počítači a prohlížeči používat 2FA. Když povolíte 2FA a kliknete na pamatovat si tento prohlížeč , získáte silnou ochranu 2FA před uživateli se zlými úmysly, kteří se pokoušejí získat přístup k vašemu účtu, pokud nemají přístup k vašemu počítači. Můžete to udělat na jakémkoli privátním počítači, který pravidelně používáte. Nastavením pamatovat si tento prohlížeč získáte z počítačů, které pravidelně nepoužíváte, zvýšené zabezpečení 2FA a získáte pohodlí, když nemusíte procházet 2FA na vlastních počítačích.
Postup registrace zprostředkovatele dvojúrovňového ověřování
Když vytvoříte nový projekt MVC, soubor IdentityConfig.cs obsahuje následující kód pro registraci zprostředkovatele dvojúrovňového ověřování:
public static ApplicationUserManager Create(
IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
var manager = new ApplicationUserManager(
new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Register two factor authentication providers. This application uses Phone and Emails as a
// step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is: {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>
(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
Přidání telefonního čísla pro 2FA
Metoda AddPhoneNumber
akce v Manage
kontroleru vygeneruje token zabezpečení a odešle ho na telefonní číslo, které jste zadali.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddPhoneNumber(AddPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Generate the token and send it
var code = await UserManager.GenerateChangePhoneNumberTokenAsync(
User.Identity.GetUserId(), model.Number);
if (UserManager.SmsService != null)
{
var message = new IdentityMessage
{
Destination = model.Number,
Body = "Your security code is: " + code
};
await UserManager.SmsService.SendAsync(message);
}
return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number });
}
Po odeslání tokenu se přesměruje na metodu VerifyPhoneNumber
akce, kde můžete zadat kód pro registraci SMS pro 2FA. SMS 2FA se nepoužívá, dokud neověříte telefonní číslo.
Povolení 2FA
Metoda EnableTFA
action povolí 2FA:
// POST: /Manage/EnableTFA
[HttpPost]
public async Task<ActionResult> EnableTFA()
{
await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", "Manage");
}
Všimněte si, SignInAsync
že je nutné volat, protože povolení 2FA je změna profilu zabezpečení. Když je 2FA povolená, bude uživatel muset k přihlášení použít 2FA s použitím 2FA přístupů, které zaregistroval (SMS a e-mail v ukázce).
Můžete přidat další poskytovatele 2FA, jako jsou generátory kódů QR, nebo můžete napsat vlastní.
Poznámka
Kódy 2FA jsou generovány pomocí algoritmu jednorázového hesla založeného na čase a kódy jsou platné po dobu šesti minut. Pokud zadání kódu trvá déle než šest minut, zobrazí se chybová zpráva Neplatný kód.
Kombinování sociálních a místních přihlašovacích účtů
Místní účty a účty na sociálních sítích můžete zkombinovat kliknutím na e-mailový odkaz. V následujícím pořadíRickAndMSFT@gmail.com se nejprve vytvoří jako místní přihlášení, ale nejprve můžete vytvořit účet jako přihlášení na sociální sítě a pak přidat místní přihlášení.
Klikněte na odkaz Spravovat . Všimněte si 0 externích přihlašovacích údajů (přihlašovacích údajů sociálních sítí) přidružených k tomuto účtu.
Klikněte na odkaz na jinou přihlašovací službu a přijměte žádosti aplikace. Oba účty byly sloučeny, budete se moct přihlásit pomocí jednoho z těchto účtů. Můžete chtít, aby vaši uživatelé přidali místní účty v případě, že je jejich služba pro ověřování sociálních sítí mimo provoz nebo je pravděpodobnější, že ztratili přístup ke svému účtu na sociální sítě.
Na následujícím obrázku je Tom sociální přihlášení (které můžete vidět v externích přihlášeních: 1 na stránce).
Kliknutím na Vybrat heslo můžete přidat místní přihlášení přidružené ke stejnému účtu.
Uzamčení účtu před útoky hrubou silou
Účty ve vaší aplikaci můžete chránit před slovníkovými útoky povolením uzamčení uživatele. Následující kód v ApplicationUserManager Create
metodě konfiguruje uzamčení:
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
Výše uvedený kód umožňuje uzamčení pouze pro dvoufaktorové ověřování. I když můžete povolit uzamčení přihlášení změnou shouldLockout
na true v Login
metodě kontroleru účtů, doporučujeme nepovolit uzamčení přihlášení, protože účet je náchylný k útokům na přihlášení doS . V ukázkovém kódu je uzamčení pro účet správce vytvořený v ApplicationDbInitializer Seed
metodě zakázané:
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
const string name = "admin@example.com";
const string roleName = "Admin";
//Create Role Admin if it does not exist
var role = roleManager.FindByName(roleName);
if (role == null)
{
role = new IdentityRole(roleName);
var roleresult = roleManager.Create(role);
}
var user = userManager.FindByName(name);
if (user == null)
{
user = new ApplicationUser { UserName = name, Email = name };
var result = userManager.Create(user, GetSecurePassword());
result = userManager.SetLockoutEnabled(user.Id, false);
}
// Add user admin to Role Admin if not already added
var rolesForUser = userManager.GetRoles(user.Id);
if (!rolesForUser.Contains(role.Name))
{
var result = userManager.AddToRole(user.Id, role.Name);
}
}
Vyžadování, aby uživatel měl ověřený e-mailový účet
Následující kód vyžaduje, aby měl uživatel před přihlášením ověřený e-mailový účet:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Require the user to have a confirmed email before they can log on.
var user = await UserManager.FindByNameAsync(model.Email);
if (user != null)
{
if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
ViewBag.errorMessage = "You must have a confirmed email to log on.";
return View("Error");
}
}
// This doen't count login failures towards lockout only two factor authentication
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password,
model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
Jak SignInManager kontroluje požadavek na 2FA
Místní přihlášení i přihlášení na sociální sítě zkontroluje, jestli je povolené 2FA. Pokud je povoleno 2FA, SignInManager
vrátí SignInStatus.RequiresVerification
metoda přihlášení a uživatel bude přesměrován na metodu SendCode
akce, kde bude muset zadat kód pro dokončení protokolu v pořadí. Pokud má uživatel Nastaveno RememberMe na místním souboru cookie uživatelů, SignInManager
vrátí se SignInStatus.Success
a nebude muset projít 2FA.
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// Require the user to have a confirmed email before they can log on.
var user = await UserManager.FindByNameAsync(model.Email);
if (user != null)
{
if (!await UserManager.IsEmailConfirmedAsync(user.Id))
{
ViewBag.errorMessage = "You must have a confirmed email to log on.";
return View("Error");
}
}
// This doen't count login failures towards lockout only two factor authentication
// To enable password failures to trigger lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password,
model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
case SignInStatus.Failure:
default:
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
}
}
Následující kód ukazuje metodu SendCode
akce. Vytvoří se SelectListItem se všemi povolenými metodami 2FA pro uživatele.
Rutina SelectListItem se předá pomocné rutině DropDownListFor, která uživateli umožňuje vybrat přístup 2FA (obvykle e-mail a SMS).
public async Task<ActionResult> SendCode(string returnUrl)
{
var userId = await SignInManager.GetVerifiedUserIdAsync();
if (userId == null)
{
return View("Error");
}
var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(userId);
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList();
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl });
}
Jakmile uživatel publikuje přístup 2FA, HTTP POST SendCode
volá se metoda akce, SignInManager
odešle kód 2FA a uživatel je přesměrován na metodu VerifyCode
akce, kde může zadat kód pro dokončení přihlášení.
//
// POST: /Account/SendCode
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SendCode(SendCodeViewModel model)
{
if (!ModelState.IsValid)
{
return View();
}
// Generate the token and send it
if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
{
return View("Error");
}
return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl });
}
Uzamčení 2FA
I když můžete nastavit uzamčení účtu při neúspěšných pokusech o přihlášení pomocí hesla, díky tomuto přístupu bude vaše přihlášení náchylné k uzamčení SYSTÉMU DOS . Doporučujeme používat uzamčení účtu jenom s 2FA.
ApplicationUserManager
Po vytvoření nastaví ukázkový kód uzamčení 2FA a MaxFailedAccessAttemptsBeforeLockout
na pět. Jakmile se uživatel přihlásí (prostřednictvím místního účtu nebo účtu na sociálních sítích), uloží se každý neúspěšný pokus o 2FA. Pokud je dosaženo maximálního počtu pokusů, uživatel se na pět minut uzamkne (můžete nastavit dobu uzamčení pomocí DefaultAccountLockoutTimeSpan
příkazu ).
Další materiály
- Doporučené prostředky ASP.NET Identity Kompletní seznam blogů identit, videí, kurzů a skvělých odkazů na SO.
- Aplikace MVC 5 se službou Facebook, Twitter, LinkedIn a Google OAuth2 Sign-on také ukazuje, jak přidat informace o profilu do tabulky uživatelů.
- ASP.NET MVC a Identity 2.0: Principy základů od Johna Attena.
- Potvrzení účtu a obnovení hesla pomocí identity ASP.NET
- Úvod do ASP.NET Identity
- Oznamujeme rtm ASP.NET Identity 2.0.0 pranav Rastogi.
- ASP.NET Identity 2.0: Nastavení ověřování účtu a autorizace Two-Factor johnem Attenem.