将UserManager.FindAsync与自定义UserStore一起使用

Akb*_*ari 14 .net c# asp.net-mvc asp.net-identity-2

我实现了一个自定义UserStore,它实现IUserStore<DatabaseLogin, int>IUserPasswordStore<DatabaseLogin, int>.

我的登录操作方法如下:

if (ModelState.IsValid)
{
    if (Authentication.Login(user.Username, user.Password))
    {
        DatabaseLogin x = await UserManager.FindAsync(user.Username, user.Password);
        DatabaseLogin Login = Authentication.FindByName(user.Username);
        if (Login != null)
        {
            ClaimsIdentity ident = await UserManager.CreateIdentityAsync(Login,
                DefaultAuthenticationTypes.ApplicationCookie);
            AuthManager.SignOut();
            AuthManager.SignIn(new AuthenticationProperties
            {
                IsPersistent = false
            }, ident);
            return RedirectToAction("Index", "Home");
        }
    }
    else
    {
        ModelState.AddModelError("", "Invalid Login");
    }
}
return View();
Run Code Online (Sandbox Code Playgroud)

在我写的自定义身份验证类中Authentication,我有一个工作正常的Login方法,FindByName方法也返回一个app用户.但是,如果我尝试SignIn使用该登录,则用户不会被识别为已验证且HttpContext.User.Identity始终为null,因此我想我必须尝试UserManager.FindAsync.

此方法调用FindByNameAsyncGetPasswordHashAsync,它始终返回null.

public Task<DatabaseLogin> FindByNameAsync(string userName)
{
    if (string.IsNullOrEmpty(userName))
        throw new ArgumentNullException("userName");
    return Task.FromResult<DatabaseLogin>(Authentication.FindByName(userName));
}

public Task<string> GetPasswordHashAsync(DatabaseLogin user)
{
    if (user == null)
        throw new ArgumentNullException("user");
    return Task.FromResult<string>(user.Password);
}
Run Code Online (Sandbox Code Playgroud)

而且 Authentication.FindByName

public static DatabaseLogin FindByName(string name)
{
    string GetUserQuery = string.Format(
        "USE db;SELECT principal_id AS id, name as userName, create_date AS CreateDate, modify_date AS modifyDate FROM sys.database_principals WHERE type='S' AND authentication_type = 1 AND name = '{0}'"
        , name);
    DatabaseLogin user;
    using (var db = new EFDbContext())
    {
        user = db.Database.SqlQuery<DatabaseLogin>(GetUserQuery).FirstOrDefault();
    }
    user.Password = Convert.ToBase64String(Encoding.ASCII.GetBytes("pass"));
    return user;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到我正在使用数据库用户,我不确定如何为它们检索哈希密码.现在,我只是存储正确密码的Base65!

我不知道我哪里出错了,欢迎任何指导.

Akb*_*ari 5

简短回答:没错.用户在其他操作方法中进行了身份验证,但显然不在当前操作方法中.

这是我遵循的过程,也许它可以帮助您调试您的应用程序.

阅读源代码后,FindAsync首先调用FindByNameAsync,然后是CheckPasswordAsync哪些引用VerifyPasswordAsync.所以它应该没问题如果我可以覆盖VerifyPasswordAsync.

我创建了一个password hasher实现的自定义IPasswordHasher,并在create我的方法中注册它UserManager:

manager.PasswordHasher = new DbPasswordHasher();
Run Code Online (Sandbox Code Playgroud)

所以到现在UserManager.FindAsync为止,我可以从中获取用户,但事实证明,无论你从哪里获得用户都没关系,因为HttpContext.User.Identity它仍然是空的!我的错误是我没有注意到用户未在当前操作中进行身份验证,在其他操作方法中它按预期工作!