2017-02-01 4 views
5

Ich habe eine ASP.NET Core MVC App, gehostet auf Azure-Websites, wo ich Session und Identity implementiert habe. Mein Problem ist, nach 30 Minuten werde ich ausgeloggt. Es spielt keine Rolle, ob ich in den letzten 30 Minuten aktiv war oder nicht.ASP.NET Core-Website Zeitüberschreitung nach 30 Minuten

Bei einigen Suchen habe ich festgestellt, dass das Problem das SecurityStamp-Zeug ist, found here. Ich habe versucht, die Umsetzung dieser durch die folgenden Schritte ausführen:

Hier ist mein Usermanager impelmentation mit dem Sicherheits Stempel Zeug:

public class UserManager : UserManager<Login> 
{ 
    public UserManager(
     IUserStore<Login> store, 
     IOptions<IdentityOptions> optionsAccessor, 
     IPasswordHasher<Login> passwordHasher, 
     IEnumerable<IUserValidator<Login>> userValidators, 
     IEnumerable<IPasswordValidator<Login>> passwordValidators, 
     ILookupNormalizer keyNormalizer, 
     IdentityErrorDescriber errors, 
     IServiceProvider services, 
     ILogger<UserManager<Login>> logger) 
     : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger) 
    { 
     // noop 
    } 

    public override bool SupportsUserSecurityStamp => true; 

    public override async Task<string> GetSecurityStampAsync(Login login) 
    { 
     return await Task.FromResult("MyToken"); 
    } 

    public override async Task<IdentityResult> UpdateSecurityStampAsync(Login login) 
    { 
     return await Task.FromResult(IdentityResult.Success); 
    } 
} 

Hier ist meine ConfigureServices Methode auf Startup.cs:

public void ConfigureServices(IServiceCollection services) 
{ 
    // Add framework services. 
    services.AddApplicationInsightsTelemetry(Configuration); 

    services.AddSingleton(_ => Configuration); 

    services.AddSingleton<IUserStore<Login>, UserStore>(); 
    services.AddSingleton<IRoleStore<Role>, RoleStore>(); 

    services.AddIdentity<Login, Role>(o => 
    { 
     o.Password.RequireDigit = false; 
     o.Password.RequireLowercase = false; 
     o.Password.RequireUppercase = false; 
     o.Password.RequiredLength = 6; 
     o.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(365); 
     o.Cookies.ApplicationCookie.SlidingExpiration = true; 
     o.Cookies.ApplicationCookie.AutomaticAuthenticate = true; 
    }) 
     .AddUserStore<UserStore>() 
     .AddUserManager<UserManager>() 
     .AddRoleStore<RoleStore>() 
     .AddRoleManager<RoleManager>() 
     .AddDefaultTokenProviders(); 

    services.AddScoped<SignInManager<Login>, SignInManager<Login>>(); 
    services.AddScoped<UserManager<Login>, UserManager<Login>>(); 

    services.Configure<AuthorizationOptions>(options => 
    { 
     options.AddPolicy("Admin", policy => policy.Requirements.Add(new AdminRoleRequirement(new RoleRepo(Configuration)))); 
     options.AddPolicy("SuperUser", policy => policy.Requirements.Add(new SuperUserRoleRequirement(new RoleRepo(Configuration)))); 
     options.AddPolicy("DataIntegrity", policy => policy.Requirements.Add(new DataIntegrityRoleRequirement(new RoleRepo(Configuration)))); 
    }); 

    services.Configure<FormOptions>(x => x.ValueCountLimit = 4096); 
    services.AddScoped<IPasswordHasher<Login>, PasswordHasher>(); 

    services.AddDistributedMemoryCache(); 
    services.AddSession(); 

    services.AddMvc(); 

    // repos 
    InjectRepos(services); 

    // services 
    InjectServices(services); 
} 

Und schließlich , hier ist meine Configure-Methode auf Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
    loggerFactory.AddDebug(); 

    app.UseApplicationInsightsRequestTelemetry(); 

    if (env.IsDevelopment()) 
    { 
     app.UseDeveloperExceptionPage(); 
     app.UseDatabaseErrorPage(); 
     app.UseBrowserLink(); 
    } 
    else 
    { 
     app.UseExceptionHandler("/home/error"); 
    } 

    app.UseStatusCodePages(); 

    app.UseStaticFiles(); 

    app.UseSession(); 
    app.UseIdentity(); 

    app.UseMiddleware(typeof (ErrorHandlingMiddleware)); 
    app.UseMiddleware(typeof (RequestLogMiddleware)); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute(
      name: "default", 
      template: "{controller=Home}/{action=Index}/{id?}"); 
    }); 
} 

W Was ist falsch mit meiner Implementierung hier?

AKTUALISIEREN: Was für eine Sekunde ... Ich habe bemerkt, dass mein UserManager keine Schnittstellen für die Sicherheitsmarke erbt, ist das, was benötigt wird?

Antwort

1

Sind Sie unter IIS gehostet? Wenn das der Fall ist, stimmt vielleicht nichts mit Ihrem Code, aber Ihr Anwendungspool könnte wiederverwendet werden (überprüfen Sie die erweiterten Einstellungen im Anwendungspool). Wenn das passiert, wird Ihre Binärdatei aus dem Speicher entladen und durch eine neue ersetzt, deren PID sich ändert?

+0

Entschuldigung, dies ist auf Azure gehostet, daher glaube ich nicht, dass ich die Kontrolle über IIS habe. – ganders

3

Dies ist einfach, weil Sie enable and configure Data Protection benötigen. Die Cookie- und Sitzungskonfiguration sieht korrekt aus. Was jetzt für Sie passiert, ist, dass jedes Mal, wenn die App wiederverwendet wird oder die Serverlasten auf einen anderen Server oder eine neue Bereitstellung verteilt werden, ein neuer Datenschutzschlüssel im Speicher erstellt wird, sodass die Sitzungsschlüssel der Benutzer ungültig sind. Also alles, was Sie tun müssen, ist fügen Sie folgendes zu Startup.cs:

services.AddDataProtection() 
     .PersistKeysToFileSystem(new DirectoryInfo(@"D:\writable\temp\directory\")) 
     .SetDefaultKeyLifetime(TimeSpan.FromDays(14)); 

Verwenden Sie die Dokumentation lernen, wie man diese richtig eingestellt und die verschiedenen Optionen in denen die Datenschutzschlüssel (Dateisystem zu speichern, redis , Registrierung usw.). Sie könnten sich den Datenschutzschlüssel als Ersatz für den Maschinenschlüssel von web.config in asp.net vorstellen.

Da Sie erwähnt haben, dass Sie Azure verwenden, können Sie das Paket Microsoft.AspNetCore.DataProtection.AzureStorage verwenden, um den Schlüssel so zu speichern, dass er bestehen bleibt. Sie könnten also use this example of how to use Azure Storage.

+0

Also wird mein Anwendungspool alle 30 Minuten wiederverwendet und mit der Zeit synchronisiert, in der ich mich zuletzt angemeldet habe? Das macht keinen Sinn für mich. – ganders

+0

Es wird wahrscheinlich nicht oft recycelt, nein. In der AspNetCore-Dokumentation wird jedoch erwähnt, dass die Datenschutzschlüssel standardmäßig im Arbeitsspeicher generiert werden. Sie schützen die Sitzungs- und Identitätscookydaten (sowie den Aktionsfilter ValidateAntiForgeryToken), die für den Benutzer bei diesem Datenschutzschlüssel nicht gültig sind Änderungen. – truemedia

+0

Ich habe gerade [die Standardeinstellungen für Datenschutz] bemerkt (https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/default-settings#data-protection-default-settings) auf Azure sind eigentlich ziemlich gut darin, dich einzurichten. Sie können einfach den Code 'services.AddDataProtection();' hinzufügen und Sie sollten laufen. Azure behält automatisch die Schlüssel für Sie bei. Auch für jeden, der IIS verwendet, funktionieren sie auch gut auf einem einzelnen Computer, ohne die Option "PersistKeysToFileSystem" zu benötigen, da die Standardeinstellungen dies gut einrichten, wie in den Dokumenten gezeigt. – truemedia

Verwandte Themen