Sapere chi è l'utente in ogni richiesta (ogni azione, ogni vista, ogni volta)

0

Ho molte classi di modelli che sono mappati da / a tabelle usando EF. Due di questi sono User e UserCookie , che sono memorizzati nelle tabelle Users e UserCookies .

public class User
{
    public long UserId { get; set; }
    public string Fullname { get; set; }
    public string Email { get; set; }

    (...)
}

public class UserCookie
{
    public long UserCookieId { get; set; }
    public long? UserId { get; set; }
    public virtual User User { get; set; }
    public string CookieValue { get; set; }
}

Ogni controller nella mia applicazione ASP.NET MVC è un figlio (eredita) di MyController , che è come questo:

public class MyController : Controller
{
    protected MyDbContext dbContext;
    protected UserCookie userCookie;
    protected User currentUser;
    protected string cookieValue;

    public MyController() : base()
    {
        this.dbContext = new MyDbContext();
        this.cookieValue = "";
        this.currentUser = null;
        this.userCookie = null;
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        HttpCookie cookie = Request.Cookies["LoginCookie"];

        if (cookie != null)
        {
            this.cookieValue = cookie.Value;
            this.userCookie = db.UserCookies.SingleOrDefault(c => c.CookieValue.Equals(cookieValue));

            if (userCookie != null)
                this.currentUser = userCookie.User;
        }
    }

    protected override ViewResult View(string viewName, string masterName, object model)
    {
        ViewBag.CurrentUser = currentUser;
        ViewBag.UserCookie = userCookie;
        ViewBag.CookieValue = cookieValue;

        return base.View(viewName, masterName, model);
    }
}

Quando l'utente effettua l'accesso, creo un cookie in lui con un valore casuale, come questo:

   public ActionResult Login(...) 
   {
        (...)

        HttpCookie cookie = new HttpCookie("LoginCookie");
        cookie.Value = Guid.NewGuid().ToString();
        Response.Cookies.Add(cookie);

        userCookie.User = user;
        userCookie.CookieValue = cookie.Value;
        db.UserCookies.Add(userCookie);

        db.SaveChanges();

Il problema con tutto ciò che ho mostrato è che sto facendo una richiesta al database in ogni richiesta HTTP (cioè, in ogni chiamata a una delle mie azioni).

Inoltre non sono contento della tabella UserCookies perché deve essere pulita e non è intuitiva. Anche Guid generato non è sicuro.

So che quanto sbagliato è tutto questo, ma ... Non riesco a capire un modo elegante per ottenere gli stessi benefici.

Il vantaggio principale di questo è che ho accesso a currentUser in ogni azione, quindi posso fare cose del genere facilmente:

    if (!currentUser.Privileges.Any(p => p.Privilege == PrivilegesEnum.Blah))
    {
         (...)
    }

Ho anche accesso a currentUser in tutte le mie visualizzazioni.

Domande:

  1. Qual è il modo più comune per ottenere questo risultato con un vero software professionale?
  2. Se volessi usare la cache (come Redis), devo cambiare un sacco di cose nello scenario presentato?
  3. Se utilizzo la cache, dovrei memorizzare solo userId anziché l'intero oggetto Utente?
posta sports 03.09.2014 - 00:33
fonte

1 risposta

1

Non dovresti mai fidarti di un semplice cookie di testo come fonte di registrazione per i dettagli dell'utente in quanto sono facilmente modificabili. Fare così ti lascerà esposto a spoofing tipo di vulnerabilità. Puoi proteggerti usando la crittografia o la firma, ma lascerei i dettagli di ciò a una libreria, se puoi, dato che i dettagli sull'implementazione possono essere complicati.

Normalmente ciò che viene fatto è solo un identificatore utente inviato al database, come una chiave primaria o un guid unico. Piuttosto che generare un nuovo guid ogni volta basta aggiungere un campo alla tabella utente nel database. Invia questo in un cookie firmato o gettalo in un server di sessione (Redis funziona bene per questo). Se hai bisogno dei dettagli dell'utente per il rendering, butta l'oggetto utente nella tua cache e cerca questo identificatore.

Fondamentalmente ciò che hai implementato sopra è un'implementazione leggera del DB Session Server di ASP.NET.

L'altra opzione utilizza una sorta di sistema Single Sign-On con attestazioni XML, ma probabilmente è eccessivo per ciò che desideri.

    
risposta data 03.09.2014 - 04:22
fonte

Leggi altre domande sui tag