it-swarm.com.de

Wie kann ich mich beim System anmelden und mich erst wieder abmelden, wenn der Benutzer auf die Schaltfläche zum Abmelden klickt?

Ich verwende eine benutzerdefinierte Implementierung der Microsoft asp.net-Identität, da ich benutzerdefinierte Tabellen habe. Deshalb habe ich eine benutzerdefinierte Implementierung aller meiner Methoden IUserStore und IUserPasswordStore angegeben.

Problem ist, wenn Benutzer sich dann nach 10 - 15 Minuten anmeldet, wird Anmeldebenutzersitzung abgelaufen, aber, was ich will, ist, es sei denn Benutzer meldet sich ab, ich möchte Benutzeranmeldung im System behalten.

Code:

public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });            
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
        }
    }

Account Controller:

[Authorize]
    public class AccountController : Controller
    {
        public AccountController()
            : this(new UserManager<UserModel>(new UserStore()))
        {
        }

        public AccountController(UserManager<UserModel> userManager)
        {
            UserManager = userManager;
        }
        public UserManager<UserModel> UserManager { get; private set; }

         [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(string email, string password, bool rememberMe = false, string returnUrl = null)
        {
            if (ModelState.IsValid)
            {
                var user = UserManager.Find(email, password);

                if (user != null)
                {
                    await SignInAsync(user, rememberMe);
                    return RedirectToLocal(returnUrl);
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                }
            }
            return View();
        }

        private async Task SignInAsync(UserModel user, bool isPersistent)
        {
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            identity.AddClaim(new Claim("FullName", user.FirstName + " " + user.LastName));
            identity.AddClaim(new Claim("Email", user.Email));
            identity.AddClaim(new Claim("Role", user.Role));
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent, ExpiresUtc = DateTime.UtcNow.AddDays(7) }, identity);
        }

 private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }
    }

Web.config:

<system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.webServer>
    <modules>
      <remove name="FormsAuthentication" />
    </modules>
  </system.webServer>

In der folgenden Zeile habe ich 7 Tage Ablaufzeit angegeben, aber die Sitzung läuft nach 10 - 15 Minuten ab:

  AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent, ExpiresUtc = DateTime.UtcNow.AddDays(7) }, identity);

Hier in meiner folgenden Frage finden Sie mein UserModel, benutzerdefinierte UserStore-Klasse , aber um diese Frage klein zu halten, gebe ich diesen Code nicht hier ein:

UserModel und UserStore

Update : Ich habe ApplicationUser-Klasse komplett ausgeschlossen. Daher ist der folgende Code für mich nutzlos und ich denke, dass mein Cookie aus diesem Grund abgelaufen ist (ich bin mir immer noch nicht sicher):

 public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });            
 }

Hinweis: ** Der Grund dafür, dass die Sitzung für eine lange Zeit aktiv bleibt, ist, dass meine MVC-Anwendung winkelgesteuert ist, z call dann passiert nichts, wenn die Sitzung abläuft, aber wenn ich meine ganze Seite aktualisiere, wird der Benutzer zur Anmeldeseite umgeleitet, aber bis dahin weiß der Benutzer, was passiert, wenn der Benutzer die Seite nicht aktualisiert.

Ihr Problem ist das Fehlen von SecurityStamp. Der Sicherheitsstempel ist eine zufällige Zeichenfolge, mit der geprüft wird, ob das Kennwort auf dem Server geändert wurde. Der Sicherheitsstempel wird im Cookie gespeichert und wird ab und zu mit der Datenbank abgeglichen. Wenn sich der Wert in der Datenbank (Geschäft) von dem Wert im Cookie unterscheidet, wird der Benutzer aufgefordert, sich anzumelden. SecurityStampValidator führt alle Überprüfungen und die Ungültigmachung von Cookies durch.

Sie verwenden einen benutzerdefinierten Speicher für Benutzer, und das ist in Ordnung, aber Ihr Speicher implementiert IUserSecurityStampStore nicht, und wenn ein Anmelde-Cookie eines Benutzers nicht den Wert SecurityStamp erhält. Dies führt zu einer Fehlfunktion von SecurityStampValidator

Ihre Optionen sind also:

  1. Implementieren Sie IUserSecurityStampStore in Ihrem Geschäft.
  2. Entfernen Sie SecurityStampValidator aus Ihrer Konfiguration.

Die zweite Option gefällt mir aus Sicherheitsgründen nicht. Sie möchten, dass Ihre Benutzer für immer angemeldet bleiben. Das bedeutet, dass der Cookie niemals ungültig wird. Wenn der Benutzer jedoch 2 Browser hat, sind beide angemeldet. Und ändern Sie das Passwort in einem der Browser - Sekunde sollte abgemeldet und nach dem Passwort gefragt werden. Ohne Prüfung des Sicherheitsstempels wird der zweite Browser nicht abgemeldet und der Cookie bleibt gültig. Stellen Sie sich nun vor, dass der zweite Browser auf einem öffentlichen Computer geöffnet ist und der Benutzer vergessen hat, sich abzumelden - keine Möglichkeit, diese Sitzung zu beenden, selbst wenn das Kennwort geändert wird.

Um IUserSecurityStampStore zu implementieren, schauen Sie sich den Vertrag an:

/// <summary>
///     Stores a user's security stamp
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TKey"></typeparam>
public interface IUserSecurityStampStore<TUser, in TKey> : IUserStore<TUser, TKey> where TUser : class, IUser<TKey>
{
    /// <summary>
    ///     Set the security stamp for the user
    /// </summary>
    /// <param name="user"></param>
    /// <param name="stamp"></param>
    /// <returns></returns>
    Task SetSecurityStampAsync(TUser user, string stamp);

    /// <summary>
    ///     Get the user security stamp
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    Task<string> GetSecurityStampAsync(TUser user);
}

Im Grunde fügt dies Ihrer Benutzertabelle eine weitere Spalte hinzu: SecurityStamp und Sie müssen dort eine Zeichenfolge speichern. Der Wert für den Stempel ist eine beliebige Zeichenfolge. Standardidentitätsimplementierung (um Zeile 734) verwendet Guid.NewGuid().ToString() - Ich schlage vor, dass Sie dasselbe tun.

Ihr Benutzerspeicher sieht ungefähr so ​​aus: 

public class UserStore : IUserStore<UserModel>, IUserPasswordStore<UserModel>, IUserSecurityStampStore<TUser>
{
    // your other methods


    public async Task SetSecurityStampAsync(TUser user, string stamp)
    {
        if (user == null)
        {
            throw new ArgumentNullException("user");
        }
        user.SecurityStamp = stamp;
        return Task.FromResult(0);
    }

    Task<string> GetSecurityStampAsync(TUser user)
    {
        if (user == null)
        {
            throw new ArgumentNullException("user");
        }
        return Task.FromResult(user.SecurityStamp);
    }
}

Denken Sie daran - Sie müssen den Benutzer bei diesem Vorgang nicht speichern. UserManager führt dies in UpdateSecurityStampAsync für Sie durch - sofern Sie diese Methode nicht selbst überschreiben.

Vergessen Sie nicht, dem SecurityStamp-Feld einen Wert zuzuweisen, wenn Sie neue Benutzer erstellen. Und aktualisieren Sie alle vorhandenen Benutzer mit einem Wert. So etwas funktioniert update MyUsersTable set SecurityStamp = convert(nvarchar(38), NewId())

3
trailmax

Controller-Methode in einem bestimmten Zeitintervall aufrufen So wird das Sitzungszeitlimit bei jedem Aufruf zurückgesetzt. Wenn Sie zum Beispiel Ihr Sitzungszeitlimit auf 30 Minuten festgelegt haben und nach 20 Minuten diese Aktion aufrufen, wird das Sitzungszeitlimit wieder auf 30 Minuten zurückgesetzt. Auf diese Weise bleibt Ihre Sitzung auch 30 Minuten nach dem Anmelden aktiv.

Platzieren Sie Ihren JQuery-Code im Layout

JQuery:

var RefreshSessionInterval;

$(document).ready(function () {        
      clearInterval(RefreshSessionInterval);
      RefreshSessionInterval = setInterval("RefreshSession()", 30000);  // change your interval time as per requirement     
});

function RefreshSession() {
       $.ajax({
            type: "POST",
            url: '@Url.Action("RefreshSession", "YourControllerName")',           
            success: function (data) {               
            },
            error: function () {
            }
       }); 
}

Controller:

Public void RefreshSession()
{
    //your session reset from this line, as i know you don't have to write any code here.
}

public bool LogOut()
{
        LogOff();
        return true;
}

void LogOut()
{       
    Session.Clear();
    Session.Abandon();
    Session.RemoveAll();
    ClearCache();        
}

void ClearCache()
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
    Response.Cache.SetNoStore();
    ////FormsAuthentication.SignOut();
}

Ich hatte das gleiche Problem und war wirklich verwirrt, weil der Benutzer auf die Anmeldeseite umgeleitet wurde, ohne dass er dazu berechtigt war. Ich hatte das Timeout auf mehr als 8 Stunden geändert, aber nichts wurde geändert. Nachdem ich viele Seiten gelesen hatte, wie zum Beispiel unerwartete Aspnet-Abmeldung oder Frequent-Unerwarteter-Benutzer-Abmeldung , stellte ich fest, dass mit dem Computerschlüssel etwas nicht stimmt, und nachdem ich den Computerschlüssel in der Datei "web.config" überprüft hatte, konnte ich das Problem feststellen mit Maschinenschlüssel. Wenn Sie den Maschinenschlüssel ändern und ihn mit anderen in Owin gleich machen, funktioniert alles gut.

3
Mohsen Shadman

Hast du es versucht 

 ExpireTimeSpan = TimeSpan.FromDays(7);

so würde dies Ihren Code machen:

public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });

            ExpireTimeSpan = TimeSpan.FromDays(7);
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
        }
    }
3
ShufflerShark

Sie sollten auch das Sitzungszeitlimit auf Anwendungspoolebene in IIS konfigurieren, wie hier beschrieben: https://technet.Microsoft.com/de-de/library/cc771956(v=ws. 10) .aspx

2
Trifon

Hier ist, was ich getan habe, als ich einen Benutzer codiert habe, um angemeldet zu bleiben ...

Code

public partial class Startup
    {

        public void ConfigureAuth(IAppBuilder app)
        {
            // Enable the application to use a cookie to store information for the signed in user
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login")
            });
// Use a cookie to temporarily store information about a user logging in with a third party login provider
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        }
    }

Account Controller

public class AccountController : Controller
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AccountController"/> class.
        /// </summary>
        public AccountController()
            : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AccountController"/> class.
        /// </summary>
        /// <param name="userManager">The user manager.</param>
        public AccountController(UserManager<ApplicationUser> userManager)
        {
            UserManager = userManager;
        }

        /// <summary>
        /// Gets the user manager.
        /// </summary>
        /// <value>
        /// The user manager.
        /// </value>
        public UserManager<ApplicationUser> UserManager { get; private set; }

        //
        // GET: /Account/Login
        /// <summary>
        /// Logins the specified return URL.
        /// </summary>
        /// <param name="returnUrl">The return URL.</param>
        /// <returns></returns>
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        //
        // POST: /Account/Login
        /// <summary>
        /// Logins the specified model.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="returnUrl">The return URL.</param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                var user = await UserManager.FindAsync(model.UserName, model.Password);
                if (user != null)
                {
                    await SignInAsync(user, model.RememberMe);
                    return RedirectToLocal(returnUrl);
                }
                else
                {
                    ModelState.AddModelError("", "Invalid username or password.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
        }

ODER .. Sie können das Sitzungszeitlimit für einen Benutzer auch auf Anwendungspoolebene in IIS konfigurieren.

1
Yaman Ahlawat

Die Lebensdauer der Sitzung (wie lange dauert es, bis die Sitzung verschwindet) und die Gültigkeitsdauer der Authentifizierung (wie lange dauert es, bis sich der Benutzer erneut anmelden muss), besteht aus zwei separaten und unterschiedlichen Zeiträumen.

Wenn die Authentifizierungslebensdauer länger als der Sitzungszeitraum ist, bedeutet dies, dass eine Sitzung mit dem bereits authentifizierten Benutzer beginnt (d. H. Der Benutzer muss sich nicht anmelden, um eine Sitzung zu initiieren).

Wenn die Authentifizierungslebensdauer kürzer ist als der Sitzungszeitraum, bedeutet dies, dass ein Benutzer vor Ablauf seiner Sitzung zur Anmeldung gezwungen wird. Ich bin nicht sicher, ob die Sitzung "aktualisiert" wird, wenn der Benutzer sich erneut authentifiziert (als Vermutung ... wahrscheinlich).

Das Festlegen sehr langer Abläufe für Sitzung und Authentifizierung ist möglicherweise keine fertigungsfertige Lösung für Pirat (d. H. Es gibt viele Möglichkeiten, wie Sitzungen "verschwinden").

Warum ist es Ihnen wichtig, wenn die Sitzung des Benutzers verschwindet und dann eine neue Sitzung gestartet wird (ohne dass sich der Benutzer anmelden muss)? Ohne ein bisschen mehr Informationen darüber, was Sie vorhaben, kann ich den Kern Ihrer Frage nicht wirklich verstehen.

0
user2845090

Überprüfen Sie die Einstellungen des Elements forms innerhalb des authentication-Elements Ihrer Datei web.config.

Beachten Sie die Standardwerte für die zwei zutreffenden Einstellungen.

  1. timeout (Standardeinstellung ist 30 Minuten)
  2. slideExpiration (True oder False/Standard-Varines bei der .NET Framework-Version)

Für Ihre Situation möchten Sie wahrscheinlich eine Timeout-Dauer von mehr als 30 Minuten und einen SlideExpiration-Wert von True.

0
JohnH