使用带有自定义UserStore的UserManager.FindAsync

14

我已经实现了一个自定义的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();
在我编写的自定义身份验证类中,Authentication,我有一个工作正常的登录方法,也有一个返回应用程序用户的FindByName 方法。但是,如果我尝试使用该登录进行SignIn,则用户不会被识别为已经认证,HttpContext.User.Identity始终为空,因此我想我必须尝试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);
}

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

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

我不知道我的问题出在哪里,欢迎任何指导。


请将您的回答从问题中转移到适当的SO答案中,您可以自己回答。 :) - Maxime Rouiller
1个回答

5
简短回答:没有问题。用户在其他操作方法中已经通过身份验证,但显然在当前操作方法中没有通过身份验证。
以下是我遵循的过程,也许它能帮助您调试应用程序。
阅读源代码后,FindAsync首先调用FindByNameAsync,然后调用引用VerifyPasswordAsyncCheckPasswordAsync。所以如果我可以覆盖VerifyPasswordAsync,那就没问题了。
我创建了一个实现IPasswordHasher的自定义密码哈希器,并在我的UserManagercreate方法中注册它,如下所示:
manager.PasswordHasher = new DbPasswordHasher();

到目前为止,我可以从 UserManager.FindAsync 获取用户,但事实证明无论从哪里获取用户都没有关系,因为 HttpContext.User.Identity 仍然为空!我的错误在于我没有注意到当前操作中的用户未经过身份验证,在其他操作方法中它的工作正常!

那对我也起作用了,我尝试了所有的东西,直到找到你的建议,在实现IPasswordHasher之后,它终于工作了...非常感谢! - Junior Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接