什么可能导致新更改的密码不允许登录?

What could be causing the newly changed password not allowing to login?

我正在使用 Web API 2 和 Identity 2。我使用 Autofac 连接了所有东西。当用户更改他的密码时,新更改的密码不起作用,除非我重新启动 api.

似乎是 Katana 和 Autofac 的问题,但我不确定去哪里找。

Global.asax.cs

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        GlobalConfiguration.Configure(ContainerConfig.Configure);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        ...
    }
}

ContainerConfig.cs

public class ContainerConfig
{
    public static void Configure(HttpConfiguration config)
    {
        // Configure the application for OAuth based flow
        const string publicClientId = "self";

        // ContainerConfig Config
        var connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
        var elasticsearchUrl = ConfigurationManager.AppSettings["ElasticSearchUrl"];
        var elasticSearchIndex = ConfigurationManager.AppSettings["ElasticSearchIndex"];

        var builder = new ContainerBuilder();

        builder.Register(c => new BimDataContext(connectionString)).InstancePerLifetimeScope();

        builder.RegisterType<ApplicationUserManager>().AsSelf();
        builder.RegisterType<ApplicationRoleManager>().AsSelf();
        builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<BimDataContext>())).AsImplementedInterfaces();
        builder.Register(c => new RoleStore<IdentityRole>(c.Resolve<BimDataContext>())).AsImplementedInterfaces();
        builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
        builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>
        {
            DataProtectionProvider = new DpapiDataProtectionProvider("Oporo.io Identity​")
        });

        builder.RegisterType<SimpleRefreshTokenProvider>().As<IAuthenticationTokenProvider>();

        builder.Register(c => new ApplicationOAuthProvider(
            publicClientId, 
            c.Resolve<ApplicationUserManager>(), 
            c.Resolve<IAuthRepository>()))
            .As<IOAuthAuthorizationServerProvider>();

        // Register your Web API controllers.
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        // UoW registration: being explicit
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();

        // Repositories registration
        builder.RegisterAssemblyTypes(typeof(ClientRepository).Assembly)
            .AsImplementedInterfaces()
            .InstancePerDependency();

        // Services registration
        builder.RegisterAssemblyTypes(typeof(ClientService).Assembly)
            .AsImplementedInterfaces()
            .InstancePerDependency();

        builder.RegisterType<EntityPersistedEventHandler>().As<IEntityPersistedEventHandler>().InstancePerRequest();
        builder.RegisterType<COBieIndexingService>().As<ICOBieIndexingService>();

        builder.RegisterAssemblyTypes(typeof(ClientSearchService).Assembly)
            .Where(t => t.Name.EndsWith("SearchService"))
            .WithParameters(new List<Parameter>
            {
                new NamedParameter("connectionstring", elasticsearchUrl),
                new NamedParameter("defaultIndex", elasticSearchIndex),
            })
            .AsImplementedInterfaces();

        builder.RegisterType<IfcFileImportTask>().As<IIfcFileImportTask>();
        builder.RegisterType<COBieFileImportTask>().As<ICOBieFileImportTask>();

        // Hangfire registration
        builder.RegisterType<BackgroundJobClient>().As<IBackgroundJobClient>();

        // OPTIONAL: Register the Autofac filter provider.
        builder.RegisterWebApiFilterProvider(config);

        // Set the dependency resolver to be Autofac.
        var container = builder.Build();
        JobActivator.Current = new AutofacJobActivator(container);
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    }
}

ApplicationUserManager.cs

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store,
        IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
    {
        // Configure validation logic for usernames
        this.UserValidator = new UserValidator<ApplicationUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords
        this.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            this.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}

Startup.Auth.cs

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

        PublicClientId = "self";

        //var provider = (IOAuthAuthorizationServerProvider) GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IOAuthAuthorizationServerProvider));
        var provider = GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope().Resolve<IOAuthAuthorizationServerProvider>();

        //var tokenProvider = (IAuthenticationTokenProvider) GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IAuthenticationTokenProvider));
        var tokenProvider = GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope().Resolve<IAuthenticationTokenProvider>();

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = provider,
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            RefreshTokenProvider = tokenProvider,
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
        };

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

问题与在 ApplicationOAuthProvider 中获取相同的用户管理器实例有关

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var container = GlobalConfiguration.Configuration.DependencyResolver.GetRootLifetimeScope();
        using (var scope = container.BeginLifetimeScope())
        {
            var userManager = scope.Resolve<ApplicationUserManager>();
            ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }

            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
                OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
                CookieAuthenticationDefaults.AuthenticationType);

           AuthenticationProperties properties = CreateProperties(user.UserName);
            properties.Dictionary.Add("as:client_id", context.ClientId ?? string.Empty);
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesIdentity);
        }
    }