.Net Core Identity SignInManager в консольном приложении без DI / WebHost - PullRequest
1 голос
/ 05 июля 2019

Я пытаюсь написать общее консольное приложение .Net Core 2.2, которое позволяет мне использовать Identity. В частности, у меня есть база данных, и я просто пытаюсь вызвать SignInManager.PasswordSignInAsync () для аутентификации имени пользователя и пароля в моей БД.

Если я запускаю это в полномасштабном .NetCore WebApp, где HttpContext и DI все построены, это прекрасно работает. Если я урежу его и просто позвоню в базовые службы, я получаю одну и ту же ошибку каждый раз.

Я пробовал варианты уже несколько дней и просто не могу понять, что мне не хватает.

Любая помощь будет принята с благодарностью.

У меня есть класс, который управляет компоновкой служб, доступных для консольного приложения.

    public class FXLoginProvider
{
    private readonly IServiceCollection _svccoll;
    private UserManager<FXUser> _um = null;
    private SignInManager<FXUser> _sm = null;

    public UserManager<FXUser> UserMgr
    {
        get { return _um ?? (_um = _svccoll.BuildServiceProvider().GetService<UserManager<FXUser>>()); }
    }
    public SignInManager<FXUser> SignInMgr
    {
        get { return _sm ?? (_sm = _svccoll.BuildServiceProvider().GetService<SignInManager<FXUser>>()); }
    }

    public FXLoginProvider()
    {
        string s = "Data Source=.\\SQLEXPRESS;Initial catalog=csNextGen;Integrated Security=True;TrustServerCertificate=True;ApplicationIntent=ReadWrite";
        _svccoll = new ServiceCollection();
        _svccoll.AddDbContext<FXDataContext>(options => { options.UseSqlServer(s); });
        _svccoll.AddIdentity<FXUser, FXUserRole>().AddDefaultTokenProviders();
        _svccoll.AddTransient<IUserStore<FXUser>, FXUserStore>();
        _svccoll.AddTransient<IRoleStore<FXUserRole>, FXRoleStore>();
        _svccoll.AddLogging();
        _svccoll.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    }
}

Тогда в моем главном приложении ...

class Program
{
    static void Main(string[] args)
    {
        try
        {
            FXUser uu = null;
            string sUsername = "user";
            string sPassword = "P$sSw0rrD#!";

            // create the service provider
            FXLoginProvider icp = new FXLoginProvider();

            // grab the sign in manager
            SignInManager<FXUser> sm1 = icp.SignInMgr;

            // fetch the user from the db, this works.
            uu = icp.UserMgr.FindByNameAsync(sUsername).Result;

            // update my security stamp, this works too
            sm1.UserManager.UpdateSecurityStampAsync(uu).GetAwaiter().GetResult();

            // I was receiving a Null context error, so I added a default context.
            sm1.Context = new DefaultHttpContext();

            var r = sm1.PasswordSignInAsync(sUsername, sPassword, false, false).GetAwaiter().GetResult();
            Console.WriteLine(r);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }
}

и всегда выдает одно и то же исключение:

Значение не может быть пустым. \ R \ nИмя параметра: поставщик

Я вижу в StackTrace, что он сбрасывает в DependencyInjection.ServiceProviderServiceExtensions ( исходный код для DI.SPSE ), потому что IServiceProvider имеет значение null; так что я предполагаю, что мне не хватает услуги в моем списке?

Ответы [ 2 ]

0 голосов
/ 08 июля 2019

Мне удалось выяснить проблему с моей реализацией.Моя ошибка была просто в том, что я не полностью заполнил контекст http по умолчанию должным образом.

 sm1.Context = new DefaultHttpContext();

должно было быть

 sm1.Context = new DefaultHttpContext() { RequestServices = icp._svccoll.BuildServiceProvider() };

Примечание: мне нужно было изменить уровень доступа _svccoll тоже.

С этим изменением я смогиспользуйте SignInManager для аутентификации в моей серверной базе данных.

Я боролся с этой проблемой в течение нескольких дней, поэтому я рад поделиться своим решением (решение доступно на GitHub ).Надеюсь, это поможет!

0 голосов
/ 06 июля 2019

SingInManager использует cookie, вы не можете использовать его в консольном приложении.Вместо этого используйте UserManager <> там метод для проверки пароля

...