web-dev-qa-db-fra.com

Authentification basée sur les rôles dans le nouveau modèle Internet MVC 4 utilisant simplemembership

J'aime la nouvelle fonctionnalité d'adhésion simple dans le modèle Internet MVC 4 avec des liens vers OAuth pour les connexions externes dans VS 2012 RTM. Pour la plupart, la fonctionnalité d'authentification fonctionne. Cependant, même après avoir passé plus de 8 heures sur ce Je ne suis pas en mesure d'implémenter une autorisation basée sur les rôles pour travailler sur mes contrôleurs. SimpleMembership s'avère tout sauf simple.

J'ai recherché stackoverflow, googlé et lu la dernière par John Galloway , essayé de nombreuses suggestions et je n'ai toujours pas pu résoudre ce problème. Tout a commencé avec l'obtention d'une erreur de connexion SQL et n'a pas pu comprendre pourquoi quand la chaîne de connexion et tout le reste était bon. Il a fallu plusieurs heures pour comprendre que c'est la classe Rôles qui pose problème.

L'attribut [Autoriser] sur les contrôleurs fonctionne comme précédemment pour l'authentification de base. Mais chaque fois que j'essaie d'utiliser des rôles, cela donne une erreur de connexion SQL (car il revient à l'ancien DefaultRolesProvider qui essaie de se connecter au fichier aspnetdb SqlExpress par défaut et échoue). Donc quelque chose comme:

[Authorize(Roles="admin")]

ne marche pas. Cela fonctionnera si je reviens aux anciens fournisseurs d'adhésion asp.net, mais je perds ensuite les tables de base de données simples, la confirmation et la récupération des bases de jetons, le hachage de mot de passe plus sécurisé et, plus important encore, les connexions externes via OAuth.

La seule chose qui fonctionne dans les vues de code et de rasoir est

User.IsInRole("admin")

ce qui est OK pour les éléments de menu et autres, mais très lourd à implémenter à l'intérieur de chaque action dans le contrôleur (et je n'aime pas qu'il teste uniquement un rôle à la fois).

J'apprécierai grandement toute indication pour résoudre ce problème.

53
Ahmed

Trouvé une réponse ici par Mehdi Golchin qui semble s'occuper de:

[Authorize(Roles="admin,editor,publisher")]

Si j'ajoute également ceci au contrôleur domestique:

 [InitializeSimpleMembership]

Étant donné que cet attribut se trouve sur le contrôleur de comptes, la base de données SimpleMembership est initialisée uniquement après la première utilisation du contrôleur de comptes, comme la connexion/l'enregistrement. Même lorsque l'utilisateur actuel est connecté à partir du cookie, la base de données n'est pas initialisée et génère donc une erreur. Une solution consiste à mettre cet attribut sur le contrôleur domestique qui est appelé lorsque je lance mon site Web. Mais, il doit ensuite être placé sur chaque contrôleur, car je vérifie les rôles et affiche différents éléments de menu en fonction du rôle.

C'est une mauvaise conception car la base de données doit être initialisée sur l'App_Start et non lors de sa première utilisation.

J'ai essayé de mettre

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

dans la fonction Global.asaxApplication_Start(), et il prend en charge la vérification des rôles dans les éléments de menu à l'aide de User.IsInRole("admin"), mais jette ensuite une erreur dans n'importe quel contrôleur avec [Authorize(Roles="admin")] , même avec l'attribut supplémentaire [InitializeSimpleMembership] est appliqué.

Donc, en ce moment, la solution est de mettre `[InitializeSimpleMembership] sur tous les contrôleurs car un utilisateur peut initialement atterrir sur n'importe quelle page en utilisant des liens externes.

Il ne peut toujours pas comprendre comment initialiser la classe SimpleRolesProvider pour faire plus de gestion des rôles au lieu de simplement User.IsInRole().

Ces choses fonctionnent mieux dans le site des pages Web de la matrice Web et, évidemment, le port MVC n'est pas complet. Il entre en conflit et se confond avec les fournisseurs d'adhésion asp.net par défaut.

[~ # ~] modifier [~ # ~] OK je ne pensais pas que le filtre [InitializeSimpleMembership] pourrait être appliqué globalement en mettant cette ligne dans le FilterConfig.cs dans le dossier App_Start:

filters.Add(new InitializeSimpleMembershipAttribute());

Cela règle ce problème. J'ai maintenant besoin d'une solution pour l'initialisation de SimpleRolesProvider, sinon je devrai écrire mon propre fournisseur de rôles.

MISE À JOUR:

Ce article de Scott Allen a résolu tous mes problèmes.

En l'incluant dans web.config:

<roleManager enabled="true" defaultProvider="simple">
  <providers>
    <clear/>
    <add name="simple" type="WebMatrix.WebData.SimpleRoleProvider,               WebMatrix.WebData"/>
  </providers>      
</roleManager>
<membership defaultProvider="simple">
  <providers>
    <clear/>
    <add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider,                          WebMatrix.WebData"/>
  </providers>
</membership>

toutes les méthodes des classes Roles et Membership deviennent disponibles et peuvent être initialisées en code comme suit:

var roles = (SimpleRoleProvider) Roles.Provider;
var membership = (SimpleMembershipProvider) Membership.Provider;
69
Ahmed

J'ai eu le même problème lorsque je déplaçais mon application Web de VS2010/MVC3 à VS2012/MVC4.

Et ne pouvait pas faire fonctionner [InitializeSimpleMembership].

J'ai découvert que l'ajout de cela à votre web.config fait l'affaire:

  <appSettings>
    <add key="enableSimpleMembership" value="false" />
  </appSettings>

Et tout fonctionne bien comme avant.

6
keun