次の方法で共有


ASP.NET Identity でユーザーの主キーを変更する

作成者: Tom FitzMacken

Visual Studio 2013 では、既定の Web アプリケーションでは、ユーザー アカウントのキーに文字列値が使用されます。 ASP.NET Identity を使用すると、データ要件を満たすようにキーの型を変更できます。 たとえば、キーの型を文字列から整数に変更できます。

このトピックでは、既定の Web アプリケーションから開始し、ユーザー アカウント キーを整数に変更する方法について説明します。 同じ変更を使用して、プロジェクトに任意の型のキーを実装できます。 既定の Web アプリケーションでこれらの変更を行う方法を示しますが、カスタマイズしたアプリケーションにも同様の変更を適用できます。 MVC または Web フォームを操作するときに必要な変更を示します。

チュートリアルで使用するソフトウェアのバージョン

  • Update 2 が適用された Visual Studio 2013 (またはそれ以降)
  • ASP.NET Identity 2.1 以降

このチュートリアルの手順を実行するには、Visual Studio 2013 Update 2 (またはそれ以降) と、ASP.NET Web アプリケーション テンプレートから作成された Web アプリケーションが必要です。 テンプレートは Update 3 で変更されました。 このトピックでは、Update 2 および Update 3 でテンプレートを変更する方法について説明します。

このトピックは、次のセクションで構成されています。

ID ユーザー クラスのキーの型を変更する

ASP.NET Web アプリケーション テンプレートから作成したプロジェクトで、ApplicationUser クラスがユーザー アカウントのキーに整数を使用することを指定します。 IdentityModels.cs で、TKey ジェネリック パラメーターの int 型を持つ IdentityUser から継承するように ApplicationUser クラスを変更します。 また、まだ実装していない 3 つのカスタマイズされたクラスの名前も渡します。

public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, 
    CustomUserClaim> 
{ 
    ...

キーの型を変更しましたが、既定では、アプリケーションの残りの部分ではキーが文字列であると見なされます。 文字列を前提とするコード内のキーの型を明示的に指定する必要があります。

ApplicationUser クラスで、次の強調表示されたコードに示すように、GenerateUserIdentityAsync メソッドを int を含むように変更します。 この変更は、Update 3 が適用された Web フォーム プロジェクト テンプレートでは必要ありません。

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; 
}

キー型を使用するカスタマイズされた ID クラスを追加する

IdentityUserRole、IdentityUserClaim、IdentityUserLogin、IdentityRole、UserStore、RoleStore などの他の ID クラスは、文字列キーを使用するように設定されています。 キーの整数を指定するこれらのクラスの新しいバージョンを作成します。 これらのクラスに多くの実装コードを提供する必要はありません。主に int をキーとして設定するだけです。

IdentityModels.cs ファイルに次のクラスを追加します。

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) 
    { 
    } 
}

キー型を使用するようにコンテキスト クラスとユーザー マネージャーを変更する

IdentityModels.cs で、強調表示されたコードに示すように、新しいカスタマイズされたクラスとキーの int を使用するように ApplicationDbContext クラスの定義を変更します。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, 
    int, CustomUserLogin, CustomUserRole, CustomUserClaim> 
{ 
    ...

ThrowIfV1Schema パラメーターは、コンストラクターで無効になっています。 ThrowIfV1Schema 値が渡されないようにコンストラクターを変更します。

public ApplicationDbContext() 
    : base("DefaultConnection") 
{ 
}

IdentityConfig.cs開き、ApplicationUserManger クラスを変更して、新しいユーザー ストア クラスを使用してデータを保持し、キーの int を使用します。

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; 
    } 
}

Update 3 テンプレートでは、ApplicationSignInManager クラスを変更する必要があります。

public class ApplicationSignInManager : SignInManager<ApplicationUser, int>
{ ... }

キー型を使用するようにスタートアップ構成を変更する

Startup.Auth.cs で、次に強調表示されているように OnValidateIdentity コードを置き換えます。 getUserIdCallback 定義では、文字列値を整数に解析することに注意してください。

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>()))
        } 
    });

プロジェクトで GetUserId メソッドの一般的な実装が認識されない場合は、ASP.NET Identity NuGet パッケージをバージョン 2.1 に更新する必要がある場合があります

ASP.NET Identity で使用されるインフラストラクチャ クラスに多くの変更を加えています。 プロジェクトをコンパイルしようとすると、多くのエラーが発生します。 幸いなことに、残りのエラーはすべて似ています。 ID クラスはキーの整数を受け取りますが、コントローラー (または Web フォーム) は文字列値を渡しています。 いずれの場合も、GetUserId<int> を呼び出して文字列から整数に変換する必要があります。 コンパイルからエラー一覧を操作するか、次の変更に従うことができます。

残りの変更は、作成するプロジェクトの種類と、Visual Studio にインストールした更新プログラムによって異なります。 関連するセクションには、次のリンクから直接移動できます

Update 2が適用された MVC の場合は、AccountController を変更してキー型を渡します

AccountController.cs ファイルを開きます。 次のメソッドを変更する必要があります。

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(); 
    } 
}

Disassociate メソッド

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 }); 
}

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); 
}

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 });
}

RemoveAccountList メソッド

public ActionResult RemoveAccountList()
{
    var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId<int>());
    ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
    return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
}

HasPassword メソッド

private bool HasPassword()
{
    var user = UserManager.FindById(User.Identity.GetUserId<int>());
    if (user != null)
    {
        return user.PasswordHash != null;
    }
    return false;
}

これで、アプリケーションを実行し、新しいユーザーを登録できるようになりました。

Update 3 が適用された MVC の場合は、AccountController と ManageController を変更してキー型を渡します

AccountController.cs ファイルを開きます。 次のメソッドを変更する必要があります。

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");
}

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 });
}

ManageController.cs ファイルを開きます。 次のメソッドを変更する必要があります。

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 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);
}

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 });
}

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 });
}

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");
}

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");
}

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);
}

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 });
}

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);
}

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);
}

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
    });
}

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 });
}

HasPassword メソッド

private bool HasPassword()
{
    var user = UserManager.FindById(User.Identity.GetUserId<int>());
    if (user != null)
    {
        return user.PasswordHash != null;
    }
    return false;
}

HasPhoneNumber メソッド

private bool HasPhoneNumber()
{
    var user = UserManager.FindById(User.Identity.GetUserId<int>());
    if (user != null)
    {
        return user.PhoneNumber != null;
    }
    return false;
}

これで、アプリケーションを実行し、新しいユーザーを登録できるようになりました。

Update 2 が適用された Web フォームの場合は、キー型を渡す [アカウント] ページを変更します

Update 2 が適用された Web フォームの場合は、次のページを変更する必要があります。

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);
}

これで、アプリケーションを実行し、新しいユーザーを登録できるようになりました。

Update 3 が適用された Web フォームの場合は、キー型を渡す [アカウント] ページを変更します

Update 3 が適用された Web フォームの場合は、次のページを変更する必要があります。

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));
    }
}

ManagePassword.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;
    }
}

アプリケーションの実行

既定の Web アプリケーション テンプレートに必要なすべての変更が完了しました。 アプリケーションを実行し、新しいユーザーを登録します。 ユーザーを登録すると、AspNetUsers テーブルに整数の ID 列があることがわかります。

new primary key

別の主キーを使用して ASP.NET Identity テーブルを以前に作成した場合は、追加の変更を加える必要があります。 可能であれば、既存のデータベースを削除するだけです。 Web アプリケーションを実行して新しいユーザーを追加すると、正しいデザインでデータベースが再作成されます。 削除できない場合は、最初にコードの移行を実行してテーブルを変更します。 ただし、新しい整数主キーは、データベースの SQL IDENTITY プロパティとして設定されません。 ID 列を IDENTITY として手動で設定する必要があります。

その他のリソース