Использование UserManager.FindAsync с пользовательским пользовательским хранилищем

Я реализовал пользовательский 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 всегда имеет значение null, поэтому я предполагаю, что мне нужно попробовать UserManager.FindAsync.

Этот метод вызывает FindByNameAsync и GetPasswordHashAsync, и он всегда возвращает 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 правильного пароля!

Я понятия не имею, где я ошибаюсь, любые рекомендации приветствуются.

Ответы

Ответ 1

Короткий ответ: ничего плохого. Пользователь аутентифицируется в других методах действий, но, по-видимому, не в текущем методе действий.

Это процесс, за которым я последовал, возможно, это поможет вам отладить ваше приложение.

После чтения исходного кода, FindAsync сначала вызовет FindByNameAsync, а затем CheckPasswordAsync, который ссылается на VerifyPasswordAsync. Так что должно быть хорошо, если бы я мог переопределить VerifyPasswordAsync.

Я создал пользовательский password hasher, который реализует IPasswordHasher, и зарегистрировал его в методе create моего UserManager следующим образом:

manager.PasswordHasher = new DbPasswordHasher();

Итак, теперь я могу получить своего пользователя от UserManager.FindAsync, но оказалось, что неважно, где вы получаете пользователя, так как HttpContext.User.Identity по-прежнему остается нулевым! Моя ошибка заключалась в том, что я не заметил, что пользователь не аутентифицирован в текущем действии, в других методах действий он работает так, как ожидалось!