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 Tom FitzMacken
Di Visual Studio 2013, aplikasi web default menggunakan nilai string untuk kunci untuk akun pengguna. ASP.NET Identity memungkinkan Anda mengubah jenis kunci untuk memenuhi persyaratan data Anda. Misalnya, Anda dapat mengubah jenis kunci dari string menjadi bilangan bulat.
Topik ini menunjukkan cara memulai dengan aplikasi web default dan mengubah kunci akun pengguna menjadi bilangan bulat. Anda dapat menggunakan modifikasi yang sama untuk mengimplementasikan semua jenis kunci dalam proyek Anda. Ini menunjukkan cara membuat perubahan ini di aplikasi web default, tetapi Anda dapat menerapkan modifikasi serupa ke aplikasi yang disesuaikan. Ini menunjukkan perubahan yang diperlukan saat bekerja dengan MVC atau Formulir Web.
Versi perangkat lunak yang digunakan dalam tutorial
- Visual Studio 2013 dengan Pembaruan 2 (atau yang lebih baru)
- ASP.NET Identity 2.1 atau yang lebih baru
Untuk melakukan langkah-langkah dalam tutorial ini, Anda harus memiliki Visual Studio 2013 Update 2 (atau yang lebih baru), dan aplikasi web yang dibuat dari templat Aplikasi Web ASP.NET. Templat berubah di Pembaruan 3. Topik ini memperlihatkan cara mengubah templat di Pembaruan 2 dan Pembaruan 3.
Topik ini berisi bagian berikut:
- Mengubah jenis kunci di kelas pengguna Identitas
- Menambahkan kelas Identitas yang dikustomisasi yang menggunakan jenis kunci
- Mengubah kelas konteks dan manajer pengguna untuk menggunakan jenis kunci
- Mengubah konfigurasi start-up untuk menggunakan jenis kunci
- Untuk MVC dengan Pembaruan 2, ubah AccountController untuk meneruskan jenis kunci
- Untuk MVC dengan Pembaruan 3, ubah AccountController dan ManageController untuk meneruskan jenis kunci
- Untuk Formulir Web dengan Pembaruan 2, ubah halaman Akun untuk meneruskan jenis kunci
- Untuk Formulir Web dengan Pembaruan 3, ubah halaman Akun untuk meneruskan jenis kunci
- Menjalankan aplikasi
- Sumber daya lainnya
Mengubah jenis kunci di kelas pengguna Identitas
Dalam proyek Anda yang dibuat dari templat aplikasi web ASP.NET, tentukan bahwa kelas ApplicationUser menggunakan bilangan bulat untuk kunci untuk akun pengguna. Di IdentityModels.cs, ubah kelas ApplicationUser untuk mewarisi dari IdentityUser yang memiliki jenis int untuk parameter generik TKey. Anda juga meneruskan nama tiga kelas yang disesuaikan yang belum Anda terapkan.
public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole,
CustomUserClaim>
{
...
Anda telah mengubah jenis kunci, tetapi, secara default, sisa aplikasi masih mengasumsikan kuncinya adalah string. Anda harus secara eksplisit menunjukkan jenis kunci dalam kode yang mengasumsikan string.
Di kelas ApplicationUser , ubah metode GenerateUserIdentityAsync untuk menyertakan int, seperti yang ditunjukkan pada kode yang disorot di bawah ini. Perubahan ini tidak diperlukan untuk proyek Formulir Web dengan templat Pembaruan 3.
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
UserManager<ApplicationUser, int> manager)
{
// Note the authenticationType must match the one defined in
// CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(
this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
Menambahkan kelas Identitas yang dikustomisasi yang menggunakan jenis kunci
Kelas Identitas lainnya, seperti IdentityUserRole, IdentityUserClaim, IdentityUserLogin, IdentityRole, UserStore, RoleStore, masih disiapkan untuk menggunakan kunci string. Buat versi baru kelas ini yang menentukan bilangan bulat untuk kunci. Anda tidak perlu memberikan banyak kode implementasi di kelas-kelas ini, Anda terutama hanya mengatur int sebagai kunci.
Tambahkan kelas berikut ke file IdentityModels.cs Anda.
public class CustomUserRole : IdentityUserRole<int> { }
public class CustomUserClaim : IdentityUserClaim<int> { }
public class CustomUserLogin : IdentityUserLogin<int> { }
public class CustomRole : IdentityRole<int, CustomUserRole>
{
public CustomRole() { }
public CustomRole(string name) { Name = name; }
}
public class CustomUserStore : UserStore<ApplicationUser, CustomRole, int,
CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public CustomUserStore(ApplicationDbContext context)
: base(context)
{
}
}
public class CustomRoleStore : RoleStore<CustomRole, int, CustomUserRole>
{
public CustomRoleStore(ApplicationDbContext context)
: base(context)
{
}
}
Mengubah kelas konteks dan manajer pengguna untuk menggunakan jenis kunci
Di IdentityModels.cs, ubah definisi kelas ApplicationDbContext untuk menggunakan kelas baru yang disesuaikan dan int untuk kunci, seperti yang ditunjukkan dalam kode yang disorot.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole,
int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
...
Parameter ThrowIfV1Schema tidak lagi valid di konstruktor. Ubah konstruktor sehingga tidak melewati nilai ThrowIfV1Schema.
public ApplicationDbContext()
: base("DefaultConnection")
{
}
Buka IdentityConfig.cs, dan ubah kelas ApplicationUserManger untuk menggunakan kelas penyimpanan pengguna baru Anda untuk menyimpan data dan int untuk kunci.
public class ApplicationUserManager : UserManager<ApplicationUser, int>
{
public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
: base(store)
{
}
public static ApplicationUserManager Create(
IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(
new CustomUserStore(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser, int>(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 in here.
manager.RegisterTwoFactorProvider("PhoneCode",
new PhoneNumberTokenProvider<ApplicationUser, int>
{
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode",
new EmailTokenProvider<ApplicationUser, int>
{
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, int>(
dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
Di templat Pembaruan 3, Anda harus mengubah kelas ApplicationSignInManager.
public class ApplicationSignInManager : SignInManager<ApplicationUser, int>
{ ... }
Mengubah konfigurasi start-up untuk menggunakan jenis kunci
Di Startup.Auth.cs, ganti kode OnValidateIdentity, seperti yang disorot di bawah ini. Perhatikan bahwa definisi getUserIdCallback, mengurai nilai string menjadi bilangan bulat.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator
.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) =>
user.GenerateUserIdentityAsync(manager),
getUserIdCallback:(id)=>(id.GetUserId<int>()))
}
});
Jika proyek Anda tidak mengenali implementasi generik metode GetUserId , Anda mungkin perlu memperbarui paket ASP.NET Identity NuGet ke versi 2.1
Anda telah membuat banyak perubahan pada kelas infrastruktur yang digunakan oleh ASP.NET Identity. Jika Anda mencoba mengkompilasi proyek, Anda akan melihat banyak kesalahan. Untungnya, kesalahan yang tersisa semuanya serupa. Kelas Identitas mengharapkan bilangan bulat untuk kunci, tetapi pengontrol (atau Formulir Web) meneruskan nilai string. Dalam setiap kasus, Anda perlu mengonversi dari string ke dan bilangan bulat dengan memanggil getUserId<int>. Anda dapat bekerja melalui daftar kesalahan dari kompilasi atau mengikuti perubahan di bawah ini.
Perubahan yang tersisa bergantung pada jenis proyek yang Anda buat dan pembaruan mana yang telah Anda instal di Visual Studio. Anda dapat langsung masuk ke bagian yang relevan melalui tautan berikut
- Untuk MVC dengan Pembaruan 2, ubah AccountController untuk meneruskan jenis kunci
- Untuk MVC dengan Pembaruan 3, ubah AccountController dan ManageController untuk meneruskan jenis kunci
- Untuk Formulir Web dengan Pembaruan 2, ubah halaman Akun untuk meneruskan jenis kunci
- Untuk Formulir Web dengan Pembaruan 3, ubah halaman Akun untuk meneruskan jenis kunci
Untuk MVC dengan Pembaruan 2, ubah AccountController untuk meneruskan jenis kunci
Buka file AccountController.cs. Anda perlu mengubah metode berikut.
Metode ConfirmEmail
public async Task<ActionResult> ConfirmEmail(int userId, string code)
{
if (userId == default(int) || code == null)
{
return View("Error");
}
IdentityResult result = await UserManager.ConfirmEmailAsync(userId, code);
if (result.Succeeded)
{
return View("ConfirmEmail");
}
else
{
AddErrors(result);
return View();
}
}
Memisahkan metode
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
{
ManageMessageId? message = null;
IdentityResult result = await UserManager.RemoveLoginAsync(
User.Identity.GetUserId<int>(),
new UserLoginInfo(loginProvider, providerKey));
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
await SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
else
{
message = ManageMessageId.Error;
}
return RedirectToAction("Manage", new { Message = message });
}
Metode Manage(ManageUserViewModel)
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = HasPassword();
ViewBag.HasLocalPassword = hasPassword;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasPassword)
{
if (ModelState.IsValid)
{
IdentityResult result = await UserManager.ChangePasswordAsync(
User.Identity.GetUserId<int>(),
model.OldPassword,
model.NewPassword);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(
User.Identity.GetUserId<int>());
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Manage", new {
Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
AddErrors(result);
}
}
}
else
{
// User does not have a password so remove any validation errors caused
// by a missing OldPassword field
ModelState state = ModelState["OldPassword"];
if (state != null)
{
state.Errors.Clear();
}
if (ModelState.IsValid)
{
IdentityResult result = await UserManager.AddPasswordAsync(
User.Identity.GetUserId<int>(), model.NewPassword);
if (result.Succeeded)
{
return RedirectToAction("Manage", new {
Message = ManageMessageId.SetPasswordSuccess });
}
else
{
AddErrors(result);
}
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Metode LinkLoginCallback
public async Task<ActionResult> LinkLoginCallback()
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey,
User.Identity.GetUserId());
if (loginInfo == null)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
}
IdentityResult result = await UserManager.AddLoginAsync(
User.Identity.GetUserId<int>(), loginInfo.Login);
if (result.Succeeded)
{
return RedirectToAction("Manage");
}
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
}
Metode RemoveAccountList
public ActionResult RemoveAccountList()
{
var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId<int>());
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
}
Metode HasPassword
private bool HasPassword()
{
var user = UserManager.FindById(User.Identity.GetUserId<int>());
if (user != null)
{
return user.PasswordHash != null;
}
return false;
}
Anda sekarang dapat menjalankan aplikasi dan mendaftarkan pengguna baru.
Untuk MVC dengan Pembaruan 3, ubah AccountController dan ManageController untuk meneruskan jenis kunci
Buka file AccountController.cs. Anda perlu mengubah metode berikut.
Metode ConfirmEmail
public async Task<ActionResult> ConfirmEmail(int userId, string code)
{
if (userId == default(int) || code == null)
{
return View("Error");
}
IdentityResult result = await UserManager.ConfirmEmailAsync(userId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
Metode SendCode
public async Task<ActionResult> SendCode(string returnUrl, bool rememberMe)
{
var userId = await SignInManager.GetVerifiedUserIdAsync();
if (userId == default(int))
{
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, RememberMe = rememberMe });
}
Buka file ManageController.cs. Anda perlu mengubah metode berikut.
Metode indeks
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 authentication provider has been set."
: message == ManageMessageId.Error ? "An error has occurred."
: message == ManageMessageId.AddPhoneSuccess ? "Your 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<int>()),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(User.Identity.GetUserId<int>()),
Logins = await UserManager.GetLoginsAsync(User.Identity.GetUserId<int>()),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(
User.Identity.GetUserId())
};
return View(model);
}
Metode RemoveLogin
public ActionResult RemoveLogin()
{
var linkedAccounts = UserManager.GetLogins((User.Identity.GetUserId<int>()));
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
return View(linkedAccounts);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> RemoveLogin(string loginProvider, string providerKey)
{
ManageMessageId? message;
var result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId<int>(),
new UserLoginInfo(loginProvider, providerKey));
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
message = ManageMessageId.RemoveLoginSuccess;
}
else
{
message = ManageMessageId.Error;
}
return RedirectToAction("ManageLogins", new { Message = message });
}
Metode AddPhoneNumber
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<int>(), 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 });
}
Metode EnableTwoFactorAuthentication
public async Task<ActionResult> EnableTwoFactorAuthentication()
{
await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId<int>(), true);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", "Manage");
}
Metode DisableTwoFactorAuthentication
public async Task<ActionResult> DisableTwoFactorAuthentication()
{
await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId<int>(), false);
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", "Manage");
}
Metode VerifyPhoneNumber
public async Task<ActionResult> VerifyPhoneNumber(string phoneNumber)
{
var code = await UserManager.GenerateChangePhoneNumberTokenAsync(
User.Identity.GetUserId<int>(), phoneNumber);
// Send an SMS through the SMS provider to verify the phone number
return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await UserManager.ChangePhoneNumberAsync(
User.Identity.GetUserId<int>(), model.PhoneNumber, model.Code);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
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 RemovePhoneNumber
public async Task<ActionResult> RemovePhoneNumber()
{
var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId<int>(), null);
if (!result.Succeeded)
{
return RedirectToAction("Index", new { Message = ManageMessageId.Error });
}
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess });
}
Metode ChangePassword
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ChangePassword(ChangePasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await UserManager.ChangePasswordAsync(
User.Identity.GetUserId<int>(), model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess });
}
AddErrors(result);
return View(model);
}
Metode SetPassword
public async Task<ActionResult> SetPassword(SetPasswordViewModel model)
{
if (ModelState.IsValid)
{
var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId<int>(), model.NewPassword);
if (result.Succeeded)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user != null)
{
await SignInAsync(user, isPersistent: false);
}
return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess });
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
Metode ManageLogins
public async Task<ActionResult> ManageLogins(ManageMessageId? message)
{
ViewBag.StatusMessage =
message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
: message == ManageMessageId.Error ? "An error has occurred."
: "";
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<int>());
if (user == null)
{
return View("Error");
}
var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId<int>());
var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList();
ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1;
return View(new ManageLoginsViewModel
{
CurrentLogins = userLogins,
OtherLogins = otherLogins
});
}
Metode LinkLoginCallback
public async Task<ActionResult> LinkLoginCallback()
{
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
if (loginInfo == null)
{
return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
}
var result = await UserManager.AddLoginAsync(User.Identity.GetUserId<int>(),
loginInfo.Login);
return result.Succeeded ? RedirectToAction("ManageLogins") :
RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error });
}
Metode HasPassword
private bool HasPassword()
{
var user = UserManager.FindById(User.Identity.GetUserId<int>());
if (user != null)
{
return user.PasswordHash != null;
}
return false;
}
Metode HasPhoneNumber
private bool HasPhoneNumber()
{
var user = UserManager.FindById(User.Identity.GetUserId<int>());
if (user != null)
{
return user.PhoneNumber != null;
}
return false;
}
Anda sekarang dapat menjalankan aplikasi dan mendaftarkan pengguna baru.
Untuk Formulir Web dengan Pembaruan 2, ubah halaman Akun untuk meneruskan jenis kunci
Untuk Formulir Web dengan Pembaruan 2, Anda perlu mengubah halaman berikut.
Confirm.aspx.cx
protected void Page_Load(object sender, EventArgs e)
{
string code = IdentityHelper.GetCodeFromRequest(Request);
string userId = IdentityHelper.GetUserIdFromRequest(Request);
if (code != null && userId != null)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.ConfirmEmail(Int32.Parse(userId), code);
if (result.Succeeded)
{
StatusMessage = "Thank you for confirming your account.";
return;
}
}
StatusMessage = "An error has occurred";
}
RegisterExternalLogin.aspx.cs
protected void Page_Load()
{
// Process the result from an auth provider in the request
ProviderName = IdentityHelper.GetProviderNameFromRequest(Request);
if (String.IsNullOrEmpty(ProviderName))
{
RedirectOnFail();
return;
}
if (!IsPostBack)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
if (loginInfo == null)
{
RedirectOnFail();
return;
}
var user = manager.Find(loginInfo.Login);
if (user != null)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else if (User.Identity.IsAuthenticated)
{
// Apply Xsrf check when linking
var verifiedloginInfo = Context.GetOwinContext().Authentication
.GetExternalLoginInfo(IdentityHelper.XsrfKey, User.Identity.GetUserId());
if (verifiedloginInfo == null)
{
RedirectOnFail();
return;
}
var result = manager.AddLogin(User.Identity.GetUserId<int>(),
verifiedloginInfo.Login);
if (result.Succeeded)
{
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"],
Response);
}
else
{
AddErrors(result);
return;
}
}
else
{
email.Text = loginInfo.Email;
}
}
}
Manage.aspx.cs
private bool HasPassword(ApplicationUserManager manager)
{
return manager.HasPassword(User.Identity.GetUserId<int>());
}
protected void Page_Load()
{
if (!IsPostBack)
{
// Determine the sections to render
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
if (HasPassword(manager))
{
changePasswordHolder.Visible = true;
}
else
{
setPassword.Visible = true;
changePasswordHolder.Visible = false;
}
CanRemoveExternalLogins = manager.GetLogins(
User.Identity.GetUserId<int>()).Count() > 1;
// Render success message
var message = Request.QueryString["m"];
if (message != null)
{
// Strip the query string from action
Form.Action = ResolveUrl("~/Account/Manage");
SuccessMessage =
message == "ChangePwdSuccess" ? "Your password has been changed."
: message == "SetPwdSuccess" ? "Your password has been set."
: message == "RemoveLoginSuccess" ? "The account was removed."
: String.Empty;
successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage);
}
}
}
protected void ChangePassword_Click(object sender, EventArgs e)
{
if (IsValid)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
IdentityResult result = manager.ChangePassword(
User.Identity.GetUserId<int>(),
CurrentPassword.Text,
NewPassword.Text);
if (result.Succeeded)
{
var user = manager.FindById(User.Identity.GetUserId<int>());
IdentityHelper.SignIn(manager, user, isPersistent: false);
Response.Redirect("~/Account/Manage?m=ChangePwdSuccess");
}
else
{
AddErrors(result);
}
}
}
protected void SetPassword_Click(object sender, EventArgs e)
{
if (IsValid)
{
// Create the local login info and link the local account to the user
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
IdentityResult result = manager.AddPassword(User.Identity.GetUserId<int>(),
password.Text);
if (result.Succeeded)
{
Response.Redirect("~/Account/Manage?m=SetPwdSuccess");
}
else
{
AddErrors(result);
}
}
}
public IEnumerable<UserLoginInfo> GetLogins()
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var accounts = manager.GetLogins(User.Identity.GetUserId<int>());
CanRemoveExternalLogins = accounts.Count() > 1 || HasPassword(manager);
return accounts;
}
public void RemoveLogin(string loginProvider, string providerKey)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.RemoveLogin(User.Identity.GetUserId<int>(),
new UserLoginInfo(loginProvider, providerKey));
string msg = String.Empty;
if (result.Succeeded)
{
var user = manager.FindById(User.Identity.GetUserId<int>());
IdentityHelper.SignIn(manager, user, isPersistent: false);
msg = "?m=RemoveLoginSuccess";
}
Response.Redirect("~/Account/Manage" + msg);
}
Anda sekarang dapat menjalankan aplikasi dan mendaftarkan pengguna baru.
Untuk Formulir Web dengan Pembaruan 3, ubah halaman Akun untuk meneruskan jenis kunci
Untuk Formulir Web dengan Pembaruan 3, Anda perlu mengubah halaman berikut.
Confirm.aspx.cx
protected void Page_Load(object sender, EventArgs e)
{
string code = IdentityHelper.GetCodeFromRequest(Request);
string userId = IdentityHelper.GetUserIdFromRequest(Request);
if (code != null && userId != null)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.ConfirmEmail(Int32.Parse(userId), code);
if (result.Succeeded)
{
StatusMessage = "Thank you for confirming your account.";
return;
}
}
StatusMessage = "An error has occurred";
}
RegisterExternalLogin.aspx.cs
protected void Page_Load()
{
// Process the result from an auth provider in the request
ProviderName = IdentityHelper.GetProviderNameFromRequest(Request);
if (String.IsNullOrEmpty(ProviderName))
{
RedirectOnFail();
return;
}
if (!IsPostBack)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo();
if (loginInfo == null)
{
RedirectOnFail();
return;
}
var user = manager.Find(loginInfo.Login);
if (user != null)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
}
else if (User.Identity.IsAuthenticated)
{
// Apply Xsrf check when linking
var verifiedloginInfo = Context.GetOwinContext().Authentication
.GetExternalLoginInfo(IdentityHelper.XsrfKey, User.Identity.GetUserId());
if (verifiedloginInfo == null)
{
RedirectOnFail();
return;
}
var result = manager.AddLogin(User.Identity.GetUserId<int>(),
verifiedloginInfo.Login);
if (result.Succeeded)
{
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"],
Response);
}
else
{
AddErrors(result);
return;
}
}
else
{
email.Text = loginInfo.Email;
}
}
}
Manage.aspx.cs
public partial class Manage : System.Web.UI.Page
{
protected string SuccessMessage
{
get;
private set;
}
private bool HasPassword(ApplicationUserManager manager)
{
return manager.HasPassword(User.Identity.GetUserId<int>());
}
public bool HasPhoneNumber { get; private set; }
public bool TwoFactorEnabled { get; private set; }
public bool TwoFactorBrowserRemembered { get; private set; }
public int LoginsCount { get; set; }
protected void Page_Load()
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
HasPhoneNumber = String.IsNullOrEmpty(manager.GetPhoneNumber(
User.Identity.GetUserId<int>()));
// Enable this after setting up two-factor authentientication
//PhoneNumber.Text = manager.GetPhoneNumber(User.Identity.GetUserId()) ?? String.Empty;
TwoFactorEnabled = manager.GetTwoFactorEnabled(User.Identity.GetUserId<int>());
LoginsCount = manager.GetLogins(User.Identity.GetUserId<int>()).Count;
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
if (!IsPostBack)
{
// Determine the sections to render
if (HasPassword(manager))
{
ChangePassword.Visible = true;
}
else
{
CreatePassword.Visible = true;
ChangePassword.Visible = false;
}
// Render success message
var message = Request.QueryString["m"];
if (message != null)
{
// Strip the query string from action
Form.Action = ResolveUrl("~/Account/Manage");
SuccessMessage =
message == "ChangePwdSuccess" ? "Your password has been changed."
: message == "SetPwdSuccess" ? "Your password has been set."
: message == "RemoveLoginSuccess" ? "The account was removed."
: message == "AddPhoneNumberSuccess" ? "Phone number has been added"
: message == "RemovePhoneNumberSuccess" ? "Phone number was removed"
: String.Empty;
successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage);
}
}
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
// Remove phonenumber from user
protected void RemovePhone_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.SetPhoneNumber(User.Identity.GetUserId<int>(), null);
if (!result.Succeeded)
{
return;
}
var user = manager.FindById(User.Identity.GetUserId<int>());
if (user != null)
{
IdentityHelper.SignIn(manager, user, isPersistent: false);
Response.Redirect("/Account/Manage?m=RemovePhoneNumberSuccess");
}
}
// DisableTwoFactorAuthentication
protected void TwoFactorDisable_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
manager.SetTwoFactorEnabled(User.Identity.GetUserId<int>(), false);
Response.Redirect("/Account/Manage");
}
//EnableTwoFactorAuthentication
protected void TwoFactorEnable_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
manager.SetTwoFactorEnabled(User.Identity.GetUserId<int>(), true);
Response.Redirect("/Account/Manage");
}
}
VerifyPhoneNumber.aspx.cs
public partial class VerifyPhoneNumber : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var phonenumber = Request.QueryString["PhoneNumber"];
var code = manager.GenerateChangePhoneNumberToken(
User.Identity.GetUserId<int>(), phonenumber);
PhoneNumber.Value = phonenumber;
}
protected void Code_Click(object sender, EventArgs e)
{
if (!ModelState.IsValid)
{
ModelState.AddModelError("", "Invalid code");
return;
}
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.ChangePhoneNumber(
User.Identity.GetUserId<int>(), PhoneNumber.Value, Code.Text);
if (result.Succeeded)
{
var user = manager.FindById(User.Identity.GetUserId<int>());
if (user != null)
{
IdentityHelper.SignIn(manager, user, false);
Response.Redirect("/Account/Manage?m=AddPhoneNumberSuccess");
}
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "Failed to verify phone");
}
}
AddPhoneNumber.aspx.cs
public partial class AddPhoneNumber : System.Web.UI.Page
{
protected void PhoneNumber_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var code = manager.GenerateChangePhoneNumberToken(
User.Identity.GetUserId<int>(), PhoneNumber.Text);
if (manager.SmsService != null)
{
var message = new IdentityMessage
{
Destination = PhoneNumber.Text,
Body = "Your security code is " + code
};
manager.SmsService.Send(message);
}
Response.Redirect("/Account/VerifyPhoneNumber?PhoneNumber=" + HttpUtility.UrlEncode(PhoneNumber.Text));
}
}
KelolaPassword.aspx.cs
public partial class ManagePassword : System.Web.UI.Page
{
protected string SuccessMessage
{
get;
private set;
}
private bool HasPassword(ApplicationUserManager manager)
{
return manager.HasPassword(User.Identity.GetUserId<int>());
}
protected void Page_Load(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
if (!IsPostBack)
{
// Determine the sections to render
if (HasPassword(manager))
{
changePasswordHolder.Visible = true;
}
else
{
setPassword.Visible = true;
changePasswordHolder.Visible = false;
}
// Render success message
var message = Request.QueryString["m"];
if (message != null)
{
// Strip the query string from action
Form.Action = ResolveUrl("~/Account/Manage");
}
}
}
protected void ChangePassword_Click(object sender, EventArgs e)
{
if (IsValid)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
IdentityResult result = manager.ChangePassword(
User.Identity.GetUserId<int>(), CurrentPassword.Text, NewPassword.Text);
if (result.Succeeded)
{
var user = manager.FindById(User.Identity.GetUserId<int>());
IdentityHelper.SignIn(manager, user, isPersistent: false);
Response.Redirect("~/Account/Manage?m=ChangePwdSuccess");
}
else
{
AddErrors(result);
}
}
}
protected void SetPassword_Click(object sender, EventArgs e)
{
if (IsValid)
{
// Create the local login info and link the local account to the user
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
IdentityResult result = manager.AddPassword(
User.Identity.GetUserId<int>(), password.Text);
if (result.Succeeded)
{
Response.Redirect("~/Account/Manage?m=SetPwdSuccess");
}
else
{
AddErrors(result);
}
}
}
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
}
ManageLogins.aspx.cs
public partial class ManageLogins : System.Web.UI.Page
{
protected string SuccessMessage
{
get;
private set;
}
protected bool CanRemoveExternalLogins
{
get;
private set;
}
private bool HasPassword(ApplicationUserManager manager)
{
return manager.HasPassword(User.Identity.GetUserId<int>());
}
protected void Page_Load(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
CanRemoveExternalLogins = manager.GetLogins(
User.Identity.GetUserId<int>()).Count() > 1;
SuccessMessage = String.Empty;
successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage);
}
public IEnumerable<UserLoginInfo> GetLogins()
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var accounts = manager.GetLogins(User.Identity.GetUserId<int>());
CanRemoveExternalLogins = accounts.Count() > 1 || HasPassword(manager);
return accounts;
}
public void RemoveLogin(string loginProvider, string providerKey)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var result = manager.RemoveLogin(
User.Identity.GetUserId<int>(), new UserLoginInfo(loginProvider, providerKey));
string msg = String.Empty;
if (result.Succeeded)
{
var user = manager.FindById(User.Identity.GetUserId<int>());
IdentityHelper.SignIn(manager, user, isPersistent: false);
msg = "?m=RemoveLoginSuccess";
}
Response.Redirect("~/Account/ManageLogins" + msg);
}
}
TwoFactorAuthenticationSignIn.aspx.cs
public partial class TwoFactorAuthenticationSignIn : System.Web.UI.Page
{
private ApplicationSignInManager signinManager;
private ApplicationUserManager manager;
public TwoFactorAuthenticationSignIn()
{
manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
signinManager = Context.GetOwinContext().GetUserManager<ApplicationSignInManager>();
}
protected void Page_Load(object sender, EventArgs e)
{
var userId = signinManager.GetVerifiedUserId<ApplicationUser, int>();
if (userId == default(int))
{
Response.Redirect("/Account/Error", true);
}
var userFactors = manager.GetValidTwoFactorProviders(userId);
Providers.DataSource = userFactors.Select(x => x).ToList();
Providers.DataBind();
}
protected void CodeSubmit_Click(object sender, EventArgs e)
{
bool rememberMe = false;
bool.TryParse(Request.QueryString["RememberMe"], out rememberMe);
var result = signinManager.TwoFactorSignIn<ApplicationUser, int>(SelectedProvider.Value, Code.Text, isPersistent: rememberMe, rememberBrowser: RememberBrowser.Checked);
switch (result)
{
case SignInStatus.Success:
IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response);
break;
case SignInStatus.LockedOut:
Response.Redirect("/Account/Lockout");
break;
case SignInStatus.Failure:
default:
FailureText.Text = "Invalid code";
ErrorMessage.Visible = true;
break;
}
}
protected void ProviderSubmit_Click(object sender, EventArgs e)
{
if (!signinManager.SendTwoFactorCode(Providers.SelectedValue))
{
Response.Redirect("/Account/Error");
}
var user = manager.FindById(signinManager.GetVerifiedUserId<ApplicationUser, int>());
if (user != null)
{
var code = manager.GenerateTwoFactorToken(user.Id, Providers.SelectedValue);
}
SelectedProvider.Value = Providers.SelectedValue;
sendcode.Visible = false;
verifycode.Visible = true;
}
}
Menjalankan aplikasi
Anda telah menyelesaikan semua perubahan yang diperlukan pada templat Aplikasi Web default. Jalankan aplikasi dan daftarkan pengguna baru. Setelah mendaftarkan pengguna, Anda akan melihat bahwa tabel AspNetUsers memiliki kolom Id yang merupakan bilangan bulat.
Jika sebelumnya Anda telah membuat tabel ASP.NET Identity dengan kunci primer yang berbeda, Anda perlu membuat beberapa perubahan tambahan. Jika memungkinkan, cukup hapus database yang ada. Database akan dibuat ulang dengan desain yang benar saat Anda menjalankan aplikasi web dan menambahkan pengguna baru. Jika penghapusan tidak dimungkinkan, jalankan migrasi pertama kode untuk mengubah tabel. Namun, kunci primer bilangan bulat baru tidak akan disiapkan sebagai properti IDENTITAS SQL dalam database. Anda harus mengatur kolom Id secara manual sebagai IDENTITY.