asp.net - mvc - asp net identify




ASP.NET MVC: imposta Personal IIdentity o IPrincipal (6)

Basato sulla risposta di LukeP e aggiungere alcuni metodi per impostare il timeout e requireSSL collaborato con Web.config .

I link di riferimento

Codici modificati di LukeP

1, Imposta il timeout base a Web.Config . FormsAuthentication.Timeout otterrà il valore di timeout, definito in web.config. Ho avvolto i seguenti come una funzione, che restituisce un ticket indietro.

int version = 1;
DateTime now = DateTime.Now;

// respect to the `timeout` in Web.config.
TimeSpan timeout = FormsAuthentication.Timeout;
DateTime expire = now.Add(timeout);
bool isPersist = false;

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
     version,          
     name,
     now,
     expire,
     isPersist,
     userData);

2, Configurare il cookie per essere sicuro o meno, in base alla configurazione RequireSSL .

HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
// respect to `RequreSSL` in `Web.Config`
bool bSSL = FormsAuthentication.RequireSSL;
faCookie.Secure = bSSL;

Devo fare qualcosa di abbastanza semplice: nella mia applicazione ASP.NET MVC, voglio impostare un IIdentity / IPrincipal personalizzato. Qualunque sia più facile / più adatto. Voglio estendere il valore predefinito in modo da poter chiamare qualcosa come User.Identity.Id e User.Identity.Role . Niente di speciale, solo alcune proprietà extra.

Ho letto un sacco di articoli e domande, ma sento che sto rendendo più difficile di quanto sia in realtà. Ho pensato che sarebbe stato facile Se un utente si connette, voglio impostare un'Identità personalizzata. Così ho pensato, implementerò Application_PostAuthenticateRequest nel mio global.asax. Tuttavia, ciò viene richiamato su ogni richiesta e non desidero effettuare una chiamata al database per ogni richiesta che richiede tutti i dati dal database e inserisce un oggetto IPrincipal personalizzato. Anche questo sembra molto inutile, lento e nel posto sbagliato (fare chiamate al database lì) ma potrei sbagliarmi. O da dove altrimenti provengono quei dati?

Così ho pensato, ogni volta che un utente si collega, posso aggiungere alcune variabili necessarie nella mia sessione, che aggiungo all'Ident personalizzato nel gestore di eventi Application_PostAuthenticateRequest . Tuttavia, il mio Context.Session è null lì, quindi non è la strada da percorrere.

Ci sto lavorando da un giorno e sento che mi manca qualcosa. Questo non dovrebbe essere troppo difficile da fare, giusto? Sono anche un po 'confuso da tutte le cose (semi) correlate a questo. MembershipProvider , MembershipUser , RoleProvider , ProfileProvider , IPrincipal , IIdentity , FormsAuthentication .... Sono l'unico che trova tutto questo molto confuso?

Se qualcuno potesse dirmi una soluzione semplice, elegante ed efficiente per archiviare alcuni dati extra su una IIdentity senza tutto il resto, sarebbe fantastico! So che ci sono domande simili su SO, ma se la risposta di cui ho bisogno è lì, devo essere trascurato.


Come aggiunta al codice LukeP per gli utenti di Web Form (non MVC) se vuoi semplificare l'accesso nel codice dietro alle tue pagine, aggiungi il codice qui sotto a una pagina di base e ricava la pagina di base in tutte le tue pagine:

Public Overridable Shadows ReadOnly Property User() As CustomPrincipal
    Get
        Return DirectCast(MyBase.User, CustomPrincipal)
    End Get
End Property

Quindi nel tuo codice dietro puoi semplicemente accedere:

User.FirstName or User.LastName

Quello che mi manca in uno scenario Web Form, è come ottenere lo stesso comportamento nel codice non legato alla pagina, ad esempio in httpmodules dovrei sempre aggiungere un cast in ogni classe o c'è un modo più intelligente per ottenere questo?

Grazie per le vostre risposte e grazie a LukeP poiché ho usato i vostri esempi come base per il mio utente personalizzato (che ora ha User.Roles , User.Tasks , User.HasPath(int) , User.Settings.Timeout e molte altre cose carine)


Ecco un esempio per portare a termine il lavoro. bool isValid è impostato guardando un data store (diciamo il tuo database di utenti). UserID è solo un ID che sto mantenendo. È possibile aggiungere informazioni aggiuntive come l'indirizzo e-mail ai dati dell'utente.

protected void btnLogin_Click(object sender, EventArgs e)
{         
    //Hard Coded for the moment
    bool isValid=true;
    if (isValid) 
    {
         string userData = String.Empty;
         userData = userData + "UserID=" + userID;
         FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30), true, userData);
         string encTicket = FormsAuthentication.Encrypt(ticket);
         HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
         Response.Cookies.Add(faCookie);
         //And send the user where they were heading
         string redirectUrl = FormsAuthentication.GetRedirectUrl(username, false);
         Response.Redirect(redirectUrl);
     }
}

nel golbal asax aggiungi il seguente codice per recuperare le tue informazioni

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[
             FormsAuthentication.FormsCookieName];
    if(authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = 
               FormsAuthentication.Decrypt(authCookie.Value);
        // Create an Identity object
        //CustomIdentity implements System.Web.Security.IIdentity
        CustomIdentity id = GetUserIdentity(authTicket.Name);
        //CustomPrincipal implements System.Web.Security.IPrincipal
        CustomPrincipal newUser = new CustomPrincipal();
        Context.User = newUser;
    }
}

Quando si intende utilizzare le informazioni in un secondo momento, è possibile accedere al principal personalizzato come segue.

(CustomPrincipal)this.User
or 
(CustomPrincipal)this.Context.User

questo ti permetterà di accedere alle informazioni utente personalizzate.


Ecco una soluzione se è necessario collegare alcuni metodi a @User per l'utilizzo nelle visualizzazioni. Nessuna soluzione per una seria personalizzazione dell'abbonamento, ma se la domanda originale fosse necessaria solo per le visualizzazioni, questo forse sarebbe sufficiente. Di seguito è stato utilizzato il controllo di una variabile restituita da un filtro autorizzabile, utilizzato per verificare se alcuni collegamenti sono da presentare o meno (non per alcun tipo di logica di autorizzazione o concessione di accesso).

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Security.Principal;

    namespace SomeSite.Web.Helpers
    {
        public static class UserHelpers
        {
            public static bool IsEditor(this IPrincipal user)
            {
                return null; //Do some stuff
            }
        }
    }

Quindi aggiungi un riferimento nelle aree web.config e chiamalo come nella vista.

@User.IsEditor()


Non posso parlare direttamente per ASP.NET MVC, ma per Web Form ASP.NET, il trucco è creare un FormsAuthenticationTicket e crittografarlo in un cookie una volta che l'utente è stato autenticato. In questo modo, è sufficiente chiamare il database una sola volta (o AD o qualsiasi altra cosa si utilizzi per eseguire l'autenticazione) e ogni richiesta successiva verrà autenticata in base al ticket memorizzato nel cookie.

Un buon articolo su questo: http://www.ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html (link non funzionante)

Modificare:

Dal momento che il link sopra è rotto, consiglierei la soluzione di LukeP nella sua risposta sopra: share - Vorrei anche suggerire che la risposta accettata sia cambiata in quella.

Modifica 2: un'alternativa per il collegamento interrotto: https://web.archive.org/web/20120422011422/http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html





iidentity