80 messaggi dal 17 maggio 2011
Ciao a tutti,

Mi sto approcciando all'implementazione del pattern MVC con autenticazione microsoft (Direi che è ora di abbandonare webform) però ho molta confusione.

In particolare sto affrontando il problema di estendere i dati collegati agli utenti e gestire i ruoli.

Da ricerche online ho trovato le soluzioni più disparate, dalle più complicate alle più semplici.
Un approccio che ho capito poco ma sembra lineare e funzionale è questo.

Nel mio identityMoldels vado ad integrare tutte le proprietà di cui necessito.

Es :
    public class ApplicationUser : IdentityUser
    {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Tenere presente che il valore di authenticationType deve corrispondere a quello definito in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Aggiungere qui i reclami utente personalizzati
            return userIdentity;
        }
        public string Name { set; get; }
        public string Surname { set; get; }
    }


Per la gestione degli utenti e dei ruoli vedo che molti creano due nuovi controller
UsersController e RolesController
Entrambe le classi vanno ad utilizzare poi ad utilizzare l'oggetto iprincipal.identity

Esempio pratico :

[Authorize]
  public class RoleController : Controller
    {
    ApplicationDbContext context;

    public RoleController()
    {
      context = new ApplicationDbContext();
    }

    /// <summary>
    /// Get All Roles
    /// </summary>
    /// <returns></returns>
    public ActionResult Index()
    {

      if (User.Identity.IsAuthenticated)
      {


        if (!isAdminUser())
        {
          return RedirectToAction("Index", "Home");
        }
      }
      else
      {
        return RedirectToAction("Index", "Home");
      }

      var Roles = context.Roles.ToList();
      return View(Roles);

    }
    public Boolean isAdminUser()
    {
      if (User.Identity.IsAuthenticated)
      {
        var user = User.Identity;
        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
        var s = UserManager.GetRoles(user.GetUserId());
        if (s[0].ToString() == "Admin")
        {
          return true;
        }
        else
        {
          return false;
        }
      }
      return false;
    }
    /// <summary>
    /// Create  a New role
    /// </summary>
    /// <returns></returns>
    public ActionResult Create()
    {
      if (User.Identity.IsAuthenticated)
      {


        if (!isAdminUser())
        {
          return RedirectToAction("Index", "Home");
        }
      }
      else
      {
        return RedirectToAction("Index", "Home");
      }

      var Role = new IdentityRole();
      return View(Role);
    }

    /// <summary>
    /// Create a New Role
    /// </summary>
    /// <param name="Role"></param>
    /// <returns></returns>
    [HttpPost]
    public ActionResult Create(IdentityRole Role)
    {
      if (User.Identity.IsAuthenticated)
      {
        if (!isAdminUser())
        {
          return RedirectToAction("Index", "Home");
        }
      }
      else
      {
        return RedirectToAction("Index", "Home");
      }

      context.Roles.Add(Role);
      context.SaveChanges();
      return RedirectToAction("Index");
    }
  }



public class UsersController : Controller
    {
    // GET: Users
    public Boolean isAdminUser()
    {
      if (User.Identity.IsAuthenticated)
      {
        var user = User.Identity;
        ApplicationDbContext context = new ApplicationDbContext();
        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
        var s = UserManager.GetRoles(user.GetUserId());
        if (s[0].ToString() == "Admin")
        {
          return true;
        }
        else
        {
          return false;
        }
      }
      return false;
    }
    public ActionResult Index()
    {
      if (User.Identity.IsAuthenticated)
      {
        var user = User.Identity;
        ViewBag.Name = user.Name;
        //  ApplicationDbContext context = new ApplicationDbContext();
        //  var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

        //var s=  UserManager.GetRoles(user.GetUserId());
        ViewBag.displayMenu = "No";

        if (isAdminUser())
        {
          ViewBag.displayMenu = "Yes";
        }
        return View();
      }
      else
      {
        ViewBag.Name = "Not Logged IN";
      }


      return View();


    }
  }


Quello che vedo mi sembra abbastanza logico, non capisco perchè utilizzare la classe user, non c'è già il controller Account di microsoft? non potrei estendere i metodi li?
Perchè è stato implementato lo stesso metodo isAdminUSer da una parte e dall'altra a che serve?

Voi cosa ne pensate è corretto questo approccio?
Avete da consigliarmi guide, approcci, video o qualsiasi altra cosa su cui mi potrei formare adeguatamente?

Grazie mille a tutti.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


Direi che è ora di abbandonare webform

Ottima decisione  Ti consiglio di passare direttamente ad ASP.NET Core MVC, che è più snello, multipiattaforma ed è quello che è maggiormente sviluppato da Microsoft in questo momento e per gli anni a venire. Qui su aspitalia abbiamo svariate risorse sul tema
http://tags.aspitalia.com/ASP.NET_Core/
E un libro in arrivo.


Nel mio identityMoldels vado ad integrare tutte le proprietà di cui necessito.

Giusto, estendere IdentityUser è proprio il modo corretto per aggiungere altre proprietà a quelle predefinite.


Per la gestione degli utenti e dei ruoli vedo che molti creano due nuovi controller
UsersController e RolesController

Ok, diciamo che gli esempi che hai trovato sono in parte corretti e in parte incasinati.
  • Sono corretti perché è giusto creare uno "UsersController" per gestire gli utenti. Infatti, la responsabilità di creare, modificare ed eliminare i dati altrui è una prerogativa di un utente amministratore. L'"AccountController", invece, serve al singolo utente per gestire i suoi dati. Contiene le action che gli consentono di fare il login, logout e così via.
    Se vuoi mettere tutto dentro AccountController lo puoi fare, non c'è nessun problema, ma io personalmente preferisco separare le action di gestione riservate agli amministratori da quelle di utilizzo comunque che ogni utente può richiamare;
  • Invece, sono incasinati perché il metodo "isAdminUser" non serve. Infatti, per consentire l'accesso ad un controller solo ad un utente con ruolo amministratore, basta usare l'attributo Authorize come vedi qui:
    [Authorize(Roles="Administrator")]
    public class RoleController : Controller
    {
      ...
    }
    

    Così è molto più semplice ed elegante. Se un utente "normale" provasse ad accedere ad una qualsiasi delle action di quel controller, verrebbe bloccato.
    Qui trovi un articolo su come funzionano autenticazione e autorizzazione con ASP.NET Core.
    http://www.aspitalia.com/articoli/asp.net-core/autenticazione-autorizzazione-aspnetcore.aspx


ciao,
Moreno

Enjoy learning and just keep making
80 messaggi dal 17 maggio 2011
Ciao Moreno,

Difficile trovare persone che rispondo in modo così preciso e dettagliato a tutte le domande.
Grazie sei stato cristallino.

Si in seguito dovrò affrontare anche CORE ma per politiche aziendali devo prima essere in grado di sviluppare e manutenere MVC.

Una piccola curiosità, mi pare di capire che le classi di Identity fornite da Microsoft quando si genera progetto autenticazione seguano il pattern MVVM e non MVC è corretto?

Tu stesso hai creato una guida per la gestione dei ruoli un paio di anni fa.
http://www.aspitalia.com/script/1194/Usare-RoleManager-Gestire-Ruoli-ASP.NET-Identity.aspx

Ho letto la guida più volte ma non riesco a capire come poterla integrare in uno scenario come quello che ho presentato io (Oppure è proprio un'alternativa e non ho capito nulla)

Ciao
Paolo
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao, ti ringrazio! Mi piace dare una mano agli altri sviluppatori in modo che riescano a risolvere i problemi. Per questo, a volte è necessario trattare il problema in maniera estensiva.


Una piccola curiosità, mi pare di capire che le classi di Identity fornite da Microsoft quando si genera progetto autenticazione seguano il pattern MVVM e non MVC è corretto?

No, è sempre MVC. Il fatto che il nome di una classe abbia il suffisso "ViewModel" non è sufficiente a chiamarlo "pattern MVVM".
Di solito un ViewModel è una classe che contiene logica di funzionamento a supporto della view, mentre in questo caso siamo in presenza di DTO anemici che non fanno altro che trasportare dei dati tra il controller e la view.



Ho letto la guida più volte ma non riesco a capire come poterla integrare in uno scenario come quello che ho presentato io (Oppure è proprio un'alternativa e non ho capito nulla)

Certo, lo puoi integrare nel tuo scenario. Se segui fedelmente le istruzioni lo puoi implementare.
Nel punto in cui scrivo questo:

Nel controller in cui desideriamo compiere operazioni sui ruoli

Nel tuo caso, il controller in questione è RoleController, da cui appunto compi operazioni sui ruoli (aggiunte, rimozioni, assegnazioni ad utenti, e così via).
Nel RoleController che hai trovato tu, i ruoli vengono aggiunti usando direttamente l'ApplicationDbContext in questo modo:
context.Roles.Add(Role);
context.SaveChanges();



Funziona, per carità, ma:
  • In quel RoleController, viene creata un'istanza dell'ApplicationDbContext ma non viene mai chiamato il metodo Dispose, e quindi avrai problemi perché la connessione al db resterà aperta.
  • Non viene usato l'oggetto canonico per la creazione dei ruoli, che è appunto il RoleManager che trattavo in quell'articolo. Finché trattiamo di ruoli, puoi anche usare ApplicationDbContext.Roles che manipola direttamente i contenuti della tabella dei ruoli ma io per sicurezza userei l'oggetto apposito RoleManager. L'importanta di questa cosa diventa ancora più evidente quando devi gestire gli utenti. In questo caso, agire direttamente su ApplicationDbContext.Users è deleterio perché non puoi attuare i criteri di protezione della password (e in ASP.NET Core anche di altri dati). Per la gestione degli utenti si usa la classe UserManager, come raccomandavo a quest'altro utente.
    http://forum.aspitalia.com/forum/post/419994/Relazione-Lambda-ApplicationUser-Tabella.aspx?PageIndex=2#420043



Se non vuoi creare tu le pagine di gestione utenti e ruoli, sappi che esiste un pacchetto nuget chiamato ASP.NET Identity Manager che però non è mai uscito dalla beta. Se gli vuoi dare un'occhiata lo stesso, qui trovi il sorgente, che ti può essere utile anche per capire come lavorare.
https://github.com/IdentityManager/IdentityManager.AspNetIdentity

E qui c'è una mia applicazione demo.
https://github.com/BrightSoul/AspNetIdentityManagerDemo

ciao,
Moreno

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.