8 messaggi dal 25 marzo 2016
Ciao,
effettivamente ci saranno più di 100 ruoli quindi devo escludere l'utilizzo dei cookies.

Ho provato a sostituire la CurrentPrincipal con una mia implementazione e sembra funzionare ma resta sempre il problema di dove salvare le roles.
Ho inserito il metodo Application_PostAuthenticateRequest nel global.asax dove vado ad assegnare allo user il mio customPrincipal

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    CustomPrincipal newUser = new CustomPrincipal(HttpContext.Current.User.Identity.Name);
    HttpContext.Current.User = newUser;
}


Nel costruttore del CustomPrincipal ho provato ad inserire i ruoli nella cache ma facendo dei test a volte la trovo vuota e va a rieseguire l'accesso al database.

Di seguito uno stralcio dell'implementazione del CustomPrincipal

public class MyRole
{
    public string Country { get; set; }
    public List<string> Roles { get; set; }
}

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
    string userID { get; set; }
    List<MyRole> MyRoles { get; set; }
}

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }
    private string userRoleCacheKey { get; set; }

    public CustomPrincipal(string username)
    {
        this.userRoleCacheKey = username;
        this.Identity = new GenericIdentity(username);
        this.userID = username;
        List<MyRole> tempMyRole = new List<MyRole>();
        if (!TryGetCachedUserRoles(username, out tempMyRole))
        {
            
      MyRole myRole = new MyRole();
      myRole.Country = GetCountry(username); // Accesso al DB
      myRole.Roles = GetUserRoles(username).ToList();  // Accesso al DB
      tempMyRole.Add(myRole);
            CacheUserRoles(username, tempMyRole);
        }

        this.MyRoles = tempMyRole;
    }
  
  private bool TryGetCachedUserRoles(string username, out List<MyRole> MyRoles)
    {
        string cacheKey = userRoleCacheKey;
        HttpContext httpContext = HttpContext.Current;
        if (httpContext != null)
        {
            MyRoles = (List<MyRole>)httpContext.Cache.Get(cacheKey) ?? new List<MyRole>();
        }
        else { MyRoles = new List<MyRole>(); }

        return MyRoles.Count() > 0;
    }

    private void CacheUserRoles(string username, List<MyRole> MyRoles)
    {
        string cacheKey = userRoleCacheKey;
        HttpContext httpContext = HttpContext.Current;
        if (httpContext != null)
        {
            httpContext.Cache.Insert(cacheKey, MyRoles, null, DateTime.UtcNow.AddMinutes(15), Cache.NoSlidingExpiration); 
        }
    }
  
  public string userID { get; set; }
    public List<MyRole> MyRoles { get; set; }
    public bool IsInRole(string role)
    {
        return Identity != null && Identity.IsAuthenticated &&
        !string.IsNullOrWhiteSpace(role) && isInRole(role);
    }

    private bool isInRole(string role)
    {
    //TODO
        return true; 
    }
}


Inoltre ho provato a mantenere il CustomRoleProvider e a salvare le roles nella cache ma anche in questo caso si verifica la medesima condizione ((List<MyRole>)httpContext.Cache.Get(cacheKey) = null).


Ti ringrazio per la tua disponibilità
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
usare la principal custom e cachare i ruoli in memoria va bene, ora devi solo identificare il problema che sta causando gli inutili accessi al db.
Per esempio vedo che quando recuperi l'oggetto dalla cache, non stai distinguendo tra null (cioè assenza di valore) e lista vuota (elenco già estratto e risultato privo di elementi).


facendo dei test a volte la trovo vuota

Ok, quindi si verifica solo in certe situazioni.
Così a occhio io non riesco ad identificare il problema nel tuo codice.
Dovresti cercare di capire quello che succede mettendo dei breakpoint ed usando il debugger oppure, meglio ancora, scrivendo degli unit tests. Non c'è sistema migliore.
Questo però significa che dovrai portare a galla le dipendenze dalla cache e dal db nel costruttore della tua classe CustomPrincipal.

ciao,
Moreno
Modificato da BrightSoul il 31 marzo 2016 19.46 -

Enjoy learning and just keep making
8 messaggi dal 25 marzo 2016
Sembrerebbe che la cache si svuoti ogni volta che si cambia pagina... Comunque domani faccio dei test più approfonditi.
Ultima domanda: é corretto mettere nel PostAuthenticateRequest il nuovo CustomPrincipal?

Grazie
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


é corretto mettere nel PostAuthenticateRequest il nuovo CustomPrincipal?

Diciamo di sì, ma non è tanto una questione di "correttezza". E' che devi aspettare che l'Identity dell'utente sia stata impostata dal modulo di autorizzazione, affinché tu possa poi leggerla per recuperarne i ruoli. Quando si verifica l'evento PostAuthenticateRequest, hai la prima opportunità di leggere l'identity ed impostare la tua Principal per la richiesta corrente.

Se preferisci non avere codice nel global.asax, puoi spostarlo in un HttpModule che ha la possibilità di sottoscriversi a qualsiasi evento che si verifica nel ciclo di vita della richiesta, compreso PostAuthenticateRequest.

ciao,
Moreno
Modificato da BrightSoul il 31 marzo 2016 20.33 -

Enjoy learning and just keep making
8 messaggi dal 25 marzo 2016
Ciao,
Rispondo solo ora perche' in questi giorni sono stato mooolto preso :-(
Sicuramente avro' sbagliato qualcosa che si risolvera' con un debug piu' approfondito! Ti ringrazio sei stato molto gentile!
Se posso vorrei approfittare facendoti un'ultima domanda, giusto per imparare ancora qualcosa :-) e' possibile nel ruleProvider utilizzare la sessione per salvare i ruoli?
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
sì, teoricamente potresti cachare i ruoli nella sessione, ma usa invece l'oggetto Cache, che ti dà un controllo più preciso sulla scadenza dei valori che ci inserisci.
  • Ti per mette di indicare il tempo esatto, trascorso il quale, il valore in cache deve scadere;
  • Puoi farla scadere on-demand usando una dependency. Utile per esempio quando un amministratore aggiorna le corrispondenze tra utenti e ruoli dal backend e vuoi che tale disposizione diventi effettiva immediatamente;
  • E' un oggetto che puoi usare sempre, al contrario della Session, che invece può essere disabilitata semplicemente usando un attributo.


Secondo una celebre frase, riuscire ad invalidare la cache al momento opportuno è una delle due cose più difficili, un po' come dare il nome alle cose.
http://martinfowler.com/bliki/TwoHardThings.html
Meglio sfruttare un oggetto come Cache, che ti permette di semplificare il problema.

ciao,
Moreno
Modificato da BrightSoul il 07 aprile 2016 22.47 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.