سؤال

For some reason I am yet to discover, but after a successful registration and activation, I cannot login with the email address, instead I get an error "Invalid login attempt".

As ASP.NET Identity 2.0 has improved with the use of Email login, I have modified the registration form to actually store a true username as the existing registration just seemed to duplicate by storing Username with the email address.

Please see below the standard code that comes with Install-Package Microsoft.AspNet.Identity.Samples -Pre' following the creation of an empty ASP.NET Web Application (MVC) project:

var user = new ApplicationUser { UserName = model.Email, Email = model.Email };

My function is now as follows:

var user = new ApplicationUser { TitleId = model.TitleId, SexId = model.SexId, Forename = model.Forename, Surname = model.Surname, UserName = model.UserName, Email = model.Email, JoinDate = System.DateTime.Now };

As you can see UserName is now receiving a value from a form. This is all well and good except now I can't logon after registration and activation. The only work round is to modify the record by putting the value from the Email field into the UserName field which just seems daft.

Can somebody please advise as to what I might have missed?

هل كانت مفيدة؟

المحلول

You have to modify SignInHelper.PasswordSignIn method. By default it uses FindByNameAsync to check if user with given name exists:

public async Task<SignInStatus> PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout)
{
    var user = await UserManager.FindByNameAsync(userName);
    // (...)

change it to use FindByEmailAsync:

    var user = await UserManager.FindByEmailAsync(userName);

You can find SignInHelper class in *AppCode\IdentityConfig.cs` file.

نصائح أخرى

In class AccountController.cs, method: public async Task<ActionResult> Login(LoginViewModel model, string returnUrl). Modified this:

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);

To this:

try
{
    var user = db.Users.Where(u => u.Email.Equals(model.Email)).Single(); // where db is ApplicationDbContext instance
    var result = await SignInManager.PasswordSignInAsync(user.UserName, model.Password, model.RememberMe, shouldLockout: false);
}
catch (InvalidOperationException)
{
    // the user is not exist
}

The reason is UserName and UserEmail have different values but method PasswordSignInAsync only uses UserName to check for log in.

I had the same issue but found the solution to be a combination of both the accepted answer by Marcin and the answer by Hai. In AccountController.cs you need to use FindByEmailAsync(), instead of FindByNameAsync(), then use SignInManager.PasswordSignInAsync() but use the value of user.UserName as the first argument (as long as user is not null), instead of model.Email. So a complete answer, based on the current boiler plate code, would be something like this:

    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        // (...) ModelState.IsValid, etc

        string user_name = ""; // in case 'user' is null (user not found)
        var user = await UserManager.FindByEmailAsync(model.Email);

        if (user != null)
        {
            user_name = user.UserName;

            if (!await UserManager.IsEmailConfirmedAsync(user.Id))
            {
                // (...) Require the user to have a confirmed email before they can log on, etc
            }
        }

        // don't use model.Email below, use the value from user.UserName (if user not null)
        var result = await SignInManager.PasswordSignInAsync(user_name, model.Password, model.RememberMe, shouldLockout: false);
        switch (result)
        {
            // (...)

You can try change to bool value in Startup.cs file in your project. "true->false" In this line, services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)

Try To Edit The "RequireConfirmedAccount" Option from "true" to "false", it worked with me, in the program class.

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
    .AddEntityFrameworkStores<ApplicationDbContext>();

If you are using default authentication code generate , in Startup file you may see below code :

services.AddDefaultIdentity<addition>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

the code forces you to use email confirm and if you didn't do that earlier you get "Invalid login attempt" error

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top