Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Hao Kung, Pranav Rastogi, Rick Anderson, Suhas Joshi
Tutorial ini akan menunjukkan kepada Anda cara menyiapkan Autentikasi dua faktor (2FA) menggunakan SMS dan email.
Artikel ini ditulis oleh Rick Anderson (@RickAndMSFT), Pranav Rastogi (@rustd), Hao Kung, dan Suhas Joshi. Sampel NuGet ditulis terutama oleh Hao Kung.
Topik ini mencakup hal-hal berikut:
- Membuat sampel Identitas
- Menyiapkan SMS untuk autentikasi Dua faktor
- Mengaktifkan autentikasi dua faktor
- Cara mendaftarkan penyedia autentikasi Dua faktor
- Menggabungkan akun login sosial dan lokal
- Penguncian akun dari serangan brute force
Membuat sampel Identitas
Di bagian ini, Anda akan menggunakan NuGet untuk mengunduh sampel yang akan kami kerjakan. Mulailah dengan menginstal dan menjalankan Visual Studio Express 2013 untuk Web atau Visual Studio 2013. Instal Visual Studio 2013 Update 2 atau yang lebih tinggi.
Catatan
Peringatan: Anda harus menginstal Visual Studio 2013 Update 2 untuk menyelesaikan tutorial ini.
Buat proyek Web ASP.NET kosong baru.
Di Konsol Manajer Paket, masukkan perintah berikut:
Install-Package SendGrid
Install-Package -Prerelease Microsoft.AspNet.Identity.Samples
Dalam tutorial ini, kita akan menggunakan SendGrid untuk mengirim email dan Twilio atau ASPSMS untuk sms sms. Paket
Identity.Samples
menginstal kode yang akan kami kerjakan.Opsional: Ikuti instruksi dalam tutorial konfirmasi Email saya untuk menghubungkan SendGrid lalu jalankan aplikasi dan daftarkan akun email.
Opsional: Hapus kode konfirmasi tautan email demo dari sampel (Kode
ViewBag.Link
di pengontrol akun.DisplayEmail
ForgotPasswordConfirmation
Lihat metode dan tindakan dan tampilan pisau cukur ).Opsional:
ViewBag.Status
Hapus kode dari pengontrol Kelola dan Akun dan dari tampilan razor Views\Account\VerifyCode.cshtml dan Views\Manage\VerifyPhoneNumber.cshtml . Atau, Anda dapat menyimpanViewBag.Status
tampilan untuk menguji cara kerja aplikasi ini secara lokal tanpa harus menghubungkan dan mengirim pesan email dan SMS.
Catatan
Peringatan: Jika Anda mengubah salah satu pengaturan keamanan dalam sampel ini, aplikasi produksi harus menjalani audit keamanan yang secara eksplisit memanggil perubahan yang dibuat.
Menyiapkan SMS untuk autentikasi Dua faktor
Tutorial ini memberikan instruksi untuk menggunakan Twilio atau ASPSMS tetapi Anda dapat menggunakan penyedia SMS lainnya.
Membuat Akun Pengguna dengan penyedia SMS
Menginstal paket tambahan atau menambahkan referensi layanan
Twilio:
Di Package Manager Console, masukkan perintah berikut:
Install-Package Twilio
ASPSMS:
Referensi layanan berikut perlu ditambahkan:Alamat:
https://webservice.aspsms.com/aspsmsx2.asmx?WSDL
Namespace:
ASPSMSX2
Mencari tahu kredensial Pengguna Penyedia SMS
Twilio:
Dari tab Dasbor akun Twilio Anda, salin SID Akun dan token Auth.ASPSMS:
Dari pengaturan akun Anda, navigasikan ke Userkey dan salin bersama dengan Kata Sandi yang ditentukan sendiri.Kita nantinya akan menyimpan nilai-nilai ini dalam variabel
SMSAccountIdentification
danSMSAccountPassword
.Menentukan SenderID / Originator
Twilio:
Dari tab Nomor , salin nomor telepon Twilio Anda.ASPSMS:
Dalam Menu Buka Kunci Originator , buka kunci satu atau beberapa Originator atau pilih Originator alfanumerik (Tidak didukung oleh semua jaringan).Kita nantinya akan menyimpan nilai ini dalam variabel
SMSAccountFrom
.Mentransfer kredensial penyedia SMS ke dalam aplikasi
Buat kredensial dan nomor telepon pengirim tersedia untuk aplikasi:
public static class Keys { public static string SMSAccountIdentification = "My Idenfitication"; public static string SMSAccountPassword = "My Password"; public static string SMSAccountFrom = "+15555551234"; }
Peringatan
Keamanan - Jangan pernah menyimpan data sensitif dalam kode sumber Anda. Akun dan kredensial ditambahkan ke kode di atas untuk menjaga sampel tetap sederhana. Lihat MVC ASP.NET Jon Atten: Jaga Pengaturan Privat Di Luar Kontrol Sumber.
Implementasi transfer data ke penyedia SMS
Konfigurasikan
SmsService
kelas dalam file App_Start\IdentityConfig.cs .Tergantung pada penyedia SMS yang digunakan, aktifkan Twilio atau bagian 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 } }
Jalankan aplikasi dan masuk dengan akun yang sebelumnya Anda daftarkan.
Klik ID Pengguna Anda, yang mengaktifkan
Index
metode tindakan diManage
pengontrol.Klik Tambahkan.
Dalam beberapa detik, Anda akan mendapatkan pesan teks dengan kode verifikasi. Masukkan dan tekan Kirim.
Tampilan Kelola memperlihatkan nomor telepon Anda telah ditambahkan.
Memeriksa kode
// 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);
}
Metode Index
tindakan di Manage
pengontrol mengatur pesan status berdasarkan tindakan Anda sebelumnya dan menyediakan tautan untuk mengubah kata sandi lokal Anda atau menambahkan akun lokal. Metode ini Index
juga menampilkan status atau nomor telepon 2FA Anda, login eksternal, 2FA diaktifkan, dan mengingat metode 2FA untuk browser ini (dijelaskan nanti). Mengklik ID pengguna (email) Anda di bilah judul tidak meneruskan pesan. Mengklik Nomor Telepon : menghapus tautan yang diteruskan Message=RemovePhoneSuccess
sebagai string kueri.
https://localhost:44300/Manage?Message=RemovePhoneSuccess
[]
Metode AddPhoneNumber
tindakan menampilkan kotak dialog untuk memasukkan nomor telepon yang dapat menerima pesan SMS.
// GET: /Account/AddPhoneNumber
public ActionResult AddPhoneNumber()
{
return View();
}
Mengklik tombol Kirim kode verifikasi memposting nomor telepon ke metode tindakan 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 });
}
Metode ini GenerateChangePhoneNumberTokenAsync
menghasilkan token keamanan yang akan diatur dalam pesan SMS. Jika layanan SMS telah dikonfigurasi, token dikirim sebagai string "Kode keamanan Anda adalah <token>". Metode SmsService.SendAsync
untuk dipanggil secara asinkron, kemudian aplikasi dialihkan ke VerifyPhoneNumber
metode tindakan (yang menampilkan dialog berikut), di mana Anda dapat memasukkan kode verifikasi.
Setelah Anda memasukkan kode dan klik kirim, kode diposting ke metode tindakan 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);
}
Metode ChangePhoneNumberAsync
memeriksa kode keamanan yang diposting. Jika kode sudah benar, nomor telepon ditambahkan ke PhoneNumber
bidang AspNetUsers
tabel. Jika panggilan tersebut berhasil, SignInAsync
metode ini disebut:
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));
}
Parameter isPersistent
mengatur apakah sesi autentikasi dipertahankan di beberapa permintaan.
Saat Anda mengubah profil keamanan, stempel keamanan baru dibuat dan disimpan di SecurityStamp
bidang tabel AspNetUsers . Perhatikan, SecurityStamp
bidang ini berbeda dari cookie keamanan. Cookie keamanan tidak disimpan dalam AspNetUsers
tabel (atau di tempat lain di DB Identitas). Token cookie keamanan ditandatangani sendiri menggunakan DPAPI dan dibuat dengan informasi waktu dan kedaluwarsa UserId, SecurityStamp
.
Middleware cookie memeriksa cookie pada setiap permintaan. Metode SecurityStampValidator
di Startup
kelas mencapai DB dan memeriksa stempel keamanan secara berkala, seperti yang ditentukan dengan validateInterval
. Ini hanya terjadi setiap 30 menit (dalam sampel kami) kecuali Anda mengubah profil keamanan Anda. Interval 30 menit dipilih untuk meminimalkan perjalanan ke database.
Metode SignInAsync
ini perlu dipanggil ketika ada perubahan yang dilakukan pada profil keamanan. Ketika profil keamanan berubah, database memperbarui SecurityStamp
bidang , dan tanpa memanggil SignInAsync
metode , Anda akan tetap masuk hanya sampai kali berikutnya alur OWIN mencapai database ( validateInterval
). Anda dapat menguji ini dengan mengubah SignInAsync
metode untuk segera kembali, dan mengatur properti cookie validateInterval
dari 30 menit ke 5 detik:
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);
Dengan perubahan kode di atas, Anda dapat mengubah profil keamanan Anda (misalnya, dengan mengubah status Dua Faktor Diaktifkan) dan Anda akan keluar dalam 5 detik ketika SecurityStampValidator.OnValidateIdentity
metode gagal. Hapus baris pengembalian dalam SignInAsync
metode , buat perubahan profil keamanan lain dan Anda tidak akan keluar. Metode ini SignInAsync
menghasilkan cookie keamanan baru.
Mengaktifkan autentikasi dua faktor
Di aplikasi sampel, Anda perlu menggunakan UI untuk mengaktifkan autentikasi dua faktor (2FA). Untuk mengaktifkan 2FA, klik ID pengguna Anda (alias email) di bilah navigasi.
Klik aktifkan 2FA.
Keluar, lalu masuk kembali. Jika Anda telah mengaktifkan email (lihat tutorial saya sebelumnya), Anda dapat memilih SMS atau email untuk 2FA.
Halaman Verifikasi Kode ditampilkan di mana Anda dapat memasukkan kode (dari SMS atau email).
Mengklik kotak centang Ingat browser ini akan membebaskan Anda dari kebutuhan untuk menggunakan 2FA untuk masuk dengan komputer dan browser tersebut. Mengaktifkan 2FA dan mengklik Ingat browser ini akan memberi Anda perlindungan 2FA yang kuat dari pengguna jahat yang mencoba mengakses akun Anda, selama mereka tidak memiliki akses ke komputer Anda. Anda dapat melakukan ini pada komputer privat apa pun yang Anda gunakan secara teratur. Dengan mengatur Ingat browser ini, Anda mendapatkan keamanan tambahan 2FA dari komputer yang tidak Anda gunakan secara teratur, dan Anda mendapatkan kenyamanan karena tidak harus melalui 2FA di komputer Anda sendiri.
Cara mendaftarkan penyedia autentikasi Dua faktor
Saat Anda membuat proyek MVC baru, file IdentityConfig.cs berisi kode berikut untuk mendaftarkan penyedia autentikasi Dua faktor:
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;
}
Menambahkan nomor telepon untuk 2FA
Metode AddPhoneNumber
tindakan dalam Manage
pengontrol menghasilkan token keamanan dan mengirimkannya ke nomor telepon yang telah Anda berikan.
[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 });
}
Setelah mengirim token, token dialihkan ke VerifyPhoneNumber
metode tindakan, di mana Anda dapat memasukkan kode untuk mendaftarkan SMS untuk 2FA. SMS 2FA tidak digunakan sampai Anda telah memverifikasi nomor telepon.
Mengaktifkan 2FA
Metode EnableTFA
tindakan memungkinkan 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");
}
Perhatikan bahwa SignInAsync
harus dipanggil karena aktifkan 2FA adalah perubahan pada profil keamanan. Ketika 2FA diaktifkan, pengguna harus menggunakan 2FA untuk masuk, menggunakan pendekatan 2FA yang telah mereka daftarkan (SMS dan email dalam sampel).
Anda dapat menambahkan lebih banyak penyedia 2FA seperti generator kode QR atau Anda dapat menulis sendiri.
Catatan
Kode 2FA dihasilkan menggunakan Algoritma Kata Sandi Satu Kali Berbasis Waktu dan kode berlaku selama enam menit. Jika Anda membutuhkan waktu lebih dari enam menit untuk memasukkan kode, Anda akan mendapatkan pesan kesalahan kode yang tidak valid.
Menggabungkan akun masuk sosial dan lokal
Anda dapat menggabungkan akun lokal dan sosial dengan mengklik tautan email Anda. Dalam urutan berikut "RickAndMSFT@gmail.com" pertama kali dibuat sebagai login lokal, tetapi Anda dapat membuat akun sebagai log sosial terlebih dahulu, lalu menambahkan login lokal.
Klik tautan Kelola . Perhatikan 0 eksternal (login sosial) yang terkait dengan akun ini.
Klik tautan ke layanan masuk lain dan terima permintaan aplikasi. Kedua akun telah digabungkan, Anda akan dapat masuk dengan salah satu akun. Anda mungkin ingin pengguna menambahkan akun lokal jika layanan autentikasi masuk sosial mereka tidak berfungsi, atau kemungkinan besar mereka telah kehilangan akses ke akun sosial mereka.
Dalam gambar berikut, Tom adalah log masuk sosial (yang dapat Anda lihat dari Login Eksternal: 1 diperlihatkan di halaman).
Mengklik Pilih kata sandi memungkinkan Anda menambahkan log lokal yang terkait dengan akun yang sama.
Penguncian akun dari serangan brute force
Anda dapat melindungi akun di aplikasi Anda dari serangan kamus dengan mengaktifkan penguncian pengguna. Kode berikut dalam ApplicationUserManager Create
metode mengonfigurasi penguncian:
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
Kode di atas hanya memungkinkan penguncian untuk autentikasi dua faktor. Meskipun Anda dapat mengaktifkan penguncian untuk masuk dengan mengubah shouldLockout
ke true dalam Login
metode pengontrol akun, kami sarankan Anda tidak mengaktifkan penguncian untuk masuk karena membuat akun rentan terhadap serangan masuk DOS . Dalam kode sampel, penguncian dinonaktifkan untuk akun admin yang dibuat dalam ApplicationDbInitializer Seed
metode :
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);
}
}
Mengharuskan pengguna memiliki akun email yang divalidasi
Kode berikut mengharuskan pengguna memiliki akun email yang divalidasi sebelum mereka dapat masuk:
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);
}
}
Cara SignInManager memeriksa persyaratan 2FA
Masuk lokal dan masuk sosial untuk melihat apakah 2FA diaktifkan. Jika 2FA diaktifkan, SignInManager
metode masuk mengembalikan SignInStatus.RequiresVerification
, dan pengguna akan dialihkan ke SendCode
metode tindakan, di mana mereka harus memasukkan kode untuk menyelesaikan log secara berurutan. Jika pengguna memiliki RememberMe diatur pada cookie lokal pengguna, SignInManager
akan kembali SignInStatus.Success
dan mereka tidak harus melalui 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 });
}
}
Kode berikut menunjukkan SendCode
metode tindakan.
SelectListItem dibuat dengan semua metode 2FA diaktifkan untuk pengguna.
SelectListItem diteruskan ke pembantu DropDownListFor, yang memungkinkan pengguna untuk memilih pendekatan 2FA (biasanya email dan 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 });
}
Setelah pengguna memposting pendekatan 2FA, HTTP POST SendCode
metode tindakan dipanggil, SignInManager
mengirim kode 2FA, dan pengguna dialihkan ke VerifyCode
metode tindakan di mana mereka dapat memasukkan kode untuk menyelesaikan masuk.
//
// 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 });
}
Penguncian 2FA
Meskipun Anda dapat mengatur penguncian akun pada kegagalan upaya kata sandi masuk, pendekatan tersebut membuat login Anda rentan terhadap penguncian DOS . Kami sarankan Anda menggunakan penguncian akun hanya dengan 2FA.
ApplicationUserManager
Saat dibuat, kode sampel mengatur penguncian 2FA dan MaxFailedAccessAttemptsBeforeLockout
ke lima. Setelah pengguna masuk (melalui akun lokal atau akun sosial), setiap upaya yang gagal di 2FA disimpan, dan jika upaya maksimum tercapai, pengguna dikunci selama lima menit (Anda dapat mengatur waktu penguncian dengan DefaultAccountLockoutTimeSpan
).
Sumber Daya Tambahan
- ASP.NET Sumber Daya yang Direkomendasikan Identitas Daftar lengkap blog Identitas, video, tutorial, dan tautan SO yang bagus.
- Aplikasi MVC 5 dengan Masuk Facebook, Twitter, LinkedIn, dan Google OAuth2 juga menunjukkan cara menambahkan informasi profil ke tabel pengguna.
- ASP.NET MVC dan Identity 2.0: Memahami Dasar-Dasar oleh John Atten.
- Konfirmasi Akun dan Pemulihan Kata Sandi dengan Identitas ASP.NET
- Pengantar Identitas ASP.NET
- Mengumumkan RTM ASP.NET Identity 2.0.0 oleh Pranav Rastogi.
- ASP.NET Identity 2.0: Menyiapkan Validasi Akun dan Otorisasi Two-Factor oleh John Atten.