简体   繁体   中英

.Net Core Identity SignInManager in Console App w/o DI/WebHost

I'm attempting to write a generic .Net Core 2.2 Console Application that allows me to use Identity. Specifically I have a database and am simply tring to call SignInManager.PasswordSignInAsync() to authenticate the username/password against my DB.

If I run this in a full blown .NetCore WebApp, where the HttpContext and DI are all built out, it works fine. If I strip it down and simply call the base services I get the same error every time.

I've been trying variants for a few days now and simply cannot figure out what I'm missing.

Any assistance would be greatly appreciated.

I have a class which manages the buildout of the services available for the console app.

    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>();
    }
}

Then in my main app...

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);
        }

    }
}

and it always throws the same exception:

Value cannot be null.\\r\\nParameter name: provider

I do see in the StackTrace it is throwing down in DependencyInjection.ServiceProviderServiceExtensions ( source code for DI.SPSE ) because the IServiceProvider is null; so I guess I'm missing a service in my list?

I was able to figure out the problem with my implementation. My error was simply that I had not completely filled in the default http context properly.

 sm1.Context = new DefaultHttpContext();

should have been

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

Note: I needed to change the access level of the _svccoll too.

With this change in place I was able to use the SignInManager to authenticate against my back end database.

I battled this problem for days so I'm happy to share my solution (solution is available on GitHub ). I hope this helps!

SingInManager relies on cookie, you can't use it in console app. Instead of it use UserManager<> there a method to verify password

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM