58 votes

Est-il possible de créer un système de connexion avec ASP.NET MVC sans utiliser le MembershipProvider ?

J'ai une base de données existante avec une table des utilisateurs, et nous prévoyons de prendre la base de données et de l'utiliser pour un nouveau système construit en ASP.NET MVC. Cependant, je ne suis pas certain de pouvoir créer un système de connexion qui n'utilise pas le contrôleur de compte intégré ou un fournisseur d'adhésion ordinaire, afin de pouvoir continuer à utiliser la structure de table existante.

Ma question est donc la suivante : est-ce que cela serait possible ? Ou même particulièrement difficile à réaliser si c'est le cas ?

Quelle est la façon de faire la plus largement acceptée et la plus simple ?

81voto

Matt Wrock Points 4772

J'avais exactement la même exigence. J'avais mon propre schéma d'utilisateurs et de rôles et je ne voulais pas migrer vers le schéma d'adhésion asp.net mais je voulais utiliser les filtres d'action ASP.NET MVC pour vérifier les autorisations et les rôles. J'ai dû faire pas mal de recherches pour savoir exactement ce qu'il fallait faire, mais finalement, c'était relativement facile. Je vais vous épargner la peine et vous dire ce que j'ai fait.

1) J'ai créé une classe dérivée de System.Web.Security.MembershipProvider. MembershipProvider a une tonne de méthodes abstraites pour toutes sortes de fonctions liées à l'authentification comme le mot de passe oublié, le changement de mot de passe, la création d'un nouvel utilisateur, etc. Tout ce que je voulais, c'était la possibilité de m'authentifier par rapport à mon propre schéma. Donc ma classe contient principalement des surcharges vides. J'ai juste surchargé ValidateUser :

public override bool ValidateUser(string username, string password)
{
    if (string.IsNullOrWhiteSpace(username) ||
        string.IsNullOrWhiteSpace(password))
      return false;

    string hash = EncryptPassword(password);
    User user = _repository.GetByUserName(username);
    if (user == null) return false;

    return user.Password == hash;
}

2) J'ai créé une classe dérivée de System.Web.Security.RoleProvider. Encore une fois, j'avais juste des implémentations vides pour toutes les choses dont je n'avais pas besoin comme la création et le changement de rôles. J'ai juste surchargé deux méthodes :

public override string[] GetRolesForUser(string username)
{
    User user = _repository.GetByUserName(username);
    string[] roles = new string[user.Role.Rights.Count + 1];
    roles[0] = user.Role.Description;
    int idx = 0;
    foreach (Right right in user.Role.Rights)
        roles[++idx] = right.Description;
    return roles;
}

public override bool IsUserInRole(string username, string roleName)
{
    User user = _repository.GetByUserName(username);
    if(user!=null)
        return user.IsInRole(roleName);
    else
        return false;
}

3) J'ai ensuite inséré ces deux classes dans mon web.config :

<membership defaultProvider="FirstlookMemberProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear/>
    <add name="FirstlookMemberProvider" type="FirstlookAdmin.DomainEntities.FirstlookMemberProvider, FirstlookAdmin" />
  </providers>
</membership>
<roleManager defaultProvider="FirstlookRoleProvider" enabled="true" cacheRolesInCookie="true">
  <providers>
    <clear/>
    <add name="FirstlookRoleProvider" type="FirstlookAdmin.DomainEntities.FirstlookRoleProvider, FirstlookAdmin" />
  </providers>
</roleManager>

C'est ça. Les filtres d'action d'autorisation par défaut utiliseront ces classes. Vous devrez toujours gérer l'ouverture et la fermeture de la page de connexion. Pour cela, utilisez les classes d'authentification des formulaires standard comme vous le feriez normalement.

11voto

Craig Stuntz Points 95965

Lorsque quelqu'un vous dit que quelque chose en rapport avec la sécurité est "facile", il a presque toujours tort. La sécurité comporte de nombreuses subtilités que les non-experts ont tendance à manquer.

En particulier, toute forme d'authentification qui ne traite pas explicitement de la mise en cache est intrinsèquement cassée. Lorsqu'un résultat d'action est mis en cache, cela se produit dans ASP.NET, et pas nécessairement dans la pile ASP.NET MVC. Si vous examinez le code source de AuthorizeAttribute, vous verrez qu'il contient un code un peu délicat mais efficace pour garantir qu'il s'exécute toujours, même lorsque le résultat de l'action est mis en cache.

La meilleure façon, et de loin, de personnaliser l'authentification ASP.NET MVC est d'écrire un fournisseur d'adhésion ASP.NET personnalisé. Je ne prétends pas que cette méthode est infaillible, mais il y a moins de risques d'avoir des problèmes avec une implémentation de sécurité défaillante qu'avec d'autres méthodes. Un avantage substantiel de cette technique est que vous pouvez substituer un système d'autorisation différent à presque tout moment, sans modification du code.

Si vous devez mettre en œuvre un attribut MVC personnalisé, vous devez sous-typer AuthorizeAttribute et remplacer AuthorizeCore, en tenant compte des commentaires du code source concernant la sécurité des fils.

10voto

Bien sûr que vous pouvez. Je l'ai fait pour mes projets en ignorant complètement le fournisseur d'adhésion.

Vous devez implémenter votre propre ActionFilter. En fait, il interceptera le contrôle avant qu'une action du contrôleur ne soit exécutée. À l'intérieur de celui-ci, vous décidez de poursuivre l'action ou de rediriger l'utilisateur vers la page de connexion.

Pour l'attribut, vous pouvez définir tous les paramètres dont vous avez besoin pour prendre en charge votre modèle d'authentification/autorisation.

public class AuthorizationAttribute : ActionFilterAttribute, IActionFilter
{
   public MyRole UserRole { get; set; }

   void IActionFilter.OnActionExecuting (ActionExecutedContext filterContext)
   {
       // Decide whether to grant access to the action or redirect away
   }
}

[Authorization (UserRole = MyRole.All)]
public class UserController : Controller
{
    [Authorization (UserRole = MyRole.Admin)]
    public ActionResult Delete ()
    {
    }
}

En ce qui concerne les préoccupations exprimées dans les commentaires. Oui, l'activation du cache de sortie interférera avec l'autorisation. Il faut simplement en être conscient.

Explication du problème : Conseil ASP.NET MVC n° 40 - Ne mettez pas en cache les pages qui nécessitent une autorisation

1voto

Robert Koritnik Points 45499

Vous avez au moins deux possibilités

  • un attribut de filtre d'action personnalisé qui fournira votre contrôle d'autorisation
  • une coutume IHttpModule qui remplira toutes les données nécessaires pour l'utilisateur connecté (y compris les rôles) et vous pouvez utiliser les filtres d'action existants

Le deuxième choix peut également être utilisé avec des formulaires Web ordinaires.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X