在编程用户创建后无法登录ASP.NET身份2站点

时间:2014-06-13 22:56:59

标签: asp.net-mvc asp.net-mvc-5 asp.net-identity-2

我有一个新的 MVC 5 razor, EF 6 Web应用程序,使用 ASP.NET Identity 2 作为成员资格系统。当我使用网页上的“注册”链接手动创建用户时,它就可以了。我可以创建用户,然后我可以使用给定的密码登录,然后注销。

我不知道如何将数据库初始化程序与Identity 2的迁移一起使用,有无数的Identity 1和其他alpha和beta版本的例子只会让人感到困惑。由于我还不知道,我使用临时MVC视图来安装成员资格。

我看到视图正常执行,我看到用户和角色以及用户与数据库中角色的关联。我还看到用户在记录中有一个哈希密码。

但是,在执行之后,我无法使用Create方法中使用的纯文本密码登录身份系统(本地),为什么?顺便说一下,我省略了try / catch并检查用户和角色创建(它们执行时没有错误)。

DbContext ctx = ApplicationDbContext.Create();
transaction = ctx.Database.BeginTransaction();
RoleManager<IdentityRole> roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(ctx));
var roleAdmin = roleManager.Create(new IdentityRole("Admin"));

var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(ctx));
ApplicationUser userAdmin = new ApplicationUser { Id = "admin", Email = "me@there.com", UserName = "admin" };
            userManager.Create(userAdmin, "Test_2013");
userManager.AddToRole(userAdmin.Id, "Admin");
userManager.Update(userAdmin);

transaction.Commit(); 

因此,如果我尝试使用电子邮件地址和Test_2013密码登录帐户,则会收到错误消息,指出用户名/密码不正确。

3 个答案:

答案 0 :(得分:32)

经过对实际数据库(身份2)和网络的大量调查后,我得出结论,没有人知道:)实际上数以百万计的网站已经过时了有关身份的信息,甚至放置已经过时的Identity 2.0代码我必须使用SQL事件探查器和SQL Management Studio进一步深入研究。

在Identity 2.0中,有一个Id属性,它是一个nvarchar()但实际上包含一个Guid。我想知道为什么微软没有把它变成一个独特的标识类型?!我在设置这个属性的时候应该把它单独放下(让它自动生成它)。

同样在Identity 2.0中有一个UserName字段,我填充了用户名。似乎UserName应该与Email相同,否则尝试登录将会失败。

答案 1 :(得分:14)

我也遇到了这个压力很大的问题。它必须使用在AccountsController中创建的默认Login方法:

 public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
        if (!ModelState.IsValid)
        {
            return View(model);
        }

        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account 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, RememberMe = model.RememberMe });
            case SignInStatus.Failure:
            default:
                ModelState.AddModelError("", "Invalid login attempt.");
                return View(model);
        }
    }

你可以看到

“等待SignInManager.PasswordSignInAsync( model.Email ,model.Password,model.RememberMe,shouldLockout:false);”

包含电子邮件作为第一个参数,但如果您检查 PasswordSignInAsync 的定义,您会看到必须接收用户名作为第一个参数而不是电子邮件。

默认情况下它起作用,因为注册新用户的方法将属性(用户名和电子邮件)设置为等于用户提供的电子邮件值。但是,如果以编程方式保存新用户并将用户名和电子邮件设置为不同的值,则登录将失败。

这无论如何都是来自 - &gt;的错误MS&lt; - “我信任那些家伙并花了几个小时试图让它工作,直到我怀疑他们”

所以你现在知道该做什么:1)更改你的登录方法以传递用户名作为第一个参数ir change注册方法以保存用户名和电子邮件不同的值。 我希望它可以帮助别人。

答案 2 :(得分:10)

LoginViewModel中存在错误。 如果你看一下Login方法(发布版本),PasswordSignInAsync方法的第一个参数应该是用户名,但是在loginViewModel中我们有电子邮件。

显然,你无法使其正常工作,因为PasswordSignInAsync实际上是将第一个参数视为用户名,而不是电子邮件地址,并且在LoginViewModel中有一个电子邮件验证器用于Email属性。

例如,您必须将LoginViewModel的电子邮件属性重命名为UserName,并删除EmailAddress注释。

然后在相应的登录视图中,您必须替换电子邮件输入字段并改为使用UserName。

然后在AccountController的login方法中,使用model.UserName作为第一个参数,它现在应该可以正常工作。