2011-10-11 4 views
2

Je suis curieux de connaître la meilleure approche pour la sécurité au niveau des données dans MVC 3. Permettez-moi de peindre une image.Sécurité au niveau des données dans MVC 3

Il existe une vue d'événement. Cet événement répertorie le nom de l'événement et une liste des joueurs qui jouent dans cet événement.

En fonction de la relation de l'utilisateur actuel avec cet événement, chaque utilisateur obtiendrait une vue sensiblement différente desservie. Par exemple, si l'utilisateur est un organisateur, l'utilisateur peut afficher et gérer la disponibilité de tous les autres utilisateurs pour cet événement.

Si l'utilisateur participe simplement à cet événement, il est évident que cet utilisateur ne peut manipuler que sa propre disponibilité.

Il y a plus de combinaisons que cela.

Je connais les filtres d'action personnalisés, mais cela semble être trop compliqué. Au lieu de cela, je suis parti pour une approche où, sur l'index de l'événement, il y a une instruction switch qui redirigera vers la vue appropriée, par ex. OrganiserEventView ou PlayerEventView.

C'est le truc facile. Je pense. Là où ça devient compliqué, c'est que j'ai utilisé un éditeur partagé pour l'énumération des PlayerModels (partie du modèle de la vue principale) pour lister les joueurs. Cet éditeur partagé lui-même devrait également respecter la sécurité au niveau des données.

Suis-je sur la bonne voie, ou existe-t-il un meilleur moyen?

+0

Bonjour, votre question est intéressante mais assez abstraite. Pouvez-vous s'il vous plaît nous donner quelques exemples détaillés? –

Répondre

0

Using Roles and custom Role Attributes semble être un bon ajustement (même si je peux dire que sans code ou une meilleure compréhension de votre base de code, personne ne peut vous donner le «meilleur» moyen) pour votre problème.

+0

Ce n'est pas basé sur des rôles, mais au niveau des données. Ainsi par exemple un utilisateur particulier pourrait être, selon les données, organisateur de l'événement 1 mais simplement un joueur de l'événement 2 – Duncan

+0

Ensuite, il semble que le filtre d'action personnalisé basé sur le propriétaire de l'événement/autres critères est le meilleur moyen aller. –

1

La réponse changera en fonction de la taille, de la complexité et de la croissance projetée de votre application. Tout en ayant la sécurité dans le contrôleur et avoir des vues différentes fonctionne, il y a des compromis. Par exemple, la réplication de code/balisage pourrait être un inconvénient. Pour les applications complexes, les portlets peuvent aider, mais ce sont des choses lourdes. Une vue peut changer en fonction des rôles de sécurité et d'accès, vous passeriez les paramètres/données du contrôleur comme n'importe quoi d'autre, si ce n'est pas déjà disponible via la session. Je voudrais créer une méthode utilitaire pour les vues à utiliser afin que les règles/logique ne finissent pas dans la vue.

+0

J'aime l'idée d'une méthode utilitaire, pouvez-vous donner un exemple rapide si ce n'est pas trop de problèmes? – Duncan

+0

Voulez-vous dire une méthode @helper? – Duncan

+0

Les annotations sont une façon d'implémenter un utilitaire, vous pouvez simplement utiliser Util.method() ou vous amuser avec Spring AOP. Simplement un simple endroit/appel. –

1

La façon dont je vois votre question, la sécurité basée sur le rôle serait la voie à suivre. Si elles sont l'organisateur, alors ils sont un rôle d'organisateur. Cependant vous avez besoin de l'abstraire un peu. Puisqu'un rôle d'organisateur serait en théorie un organisateur pour tous les autres événements, vous avez besoin d'une méthode qui détermine et remplit les rôles à la demande. Ainsi, l'utilisateur A est organisateur de l'événement A, mais pas organisateur de l'événement B. avant que le code du contrôleur ne soit accédé, vos choix sont global.asax.cs ou un filtre d'authentification.

+0

Merci, je vais enquêter. Cela semble un peu OTT pour ma solution simple mais je crois que c'est une solution très évolutive pour un système plus complexe. – Duncan

3

Duncan,

C'est quelque chose que je rencontre dans toutes les applications. Voici un contexte: Je travaille dans un département d'une grande université, nous devons donc gérer plusieurs sources de données. La plupart de nos applications sont dotées d'une sécurité qui intègre les services de sécurité «centraux informatiques» de l'université tels que l'authentification centralisée et le répertoire actif, ainsi que les rôles et autorisations «maison».Nos applications doivent présenter différentes vues et actions pour différents utilisateurs en fonction des données des deux applications "maison" (utilisées en interne dans notre département) et des données d'entreprise. Après avoir cherché un peu juste et ne trouvant pas une bonne solution à ce problème partout, j'ai fini par écrire un cadre de sécurité pour notre utilisation. Je pourrais aussi bien aller de l'avant et décrire ce qu'il fait ici. Voici ce qui est en jeu:

  1. Rôles statiques et dynamiques. Les rôles statiques sont indépendants des données (par exemple, j'obtiens un rôle de développeur dans les applications), tandis que les rôles dynamiques dépendent du contexte SecurityContext (par exemple, l'agent financier d'un département obtient le rôle d'agent fiscal).
  2. Autorisations affectées à des rôles statiques ou dynamiques.
  3. SecurityContext qui encapsule toutes les données nécessaires pour effectuer une vérification des autorisations, y compris l'utilisateur actuel et toutes les données (par exemple, numéros de compte, ID de document de proposition, dates de transaction, etc.).
  4. SecurityContextValidator qui accepte un SecurityContext et renvoie un ensemble ou des rôles valides pour l'utilisateur spécifié dans le SecurityContext spécifié. Donc la logique qui détermine qui peut voir ce qui est dans cette classe.
  5. Un SecurityContextValidator par SecurityContext. Ce mappage est enregistré à l'initialisation avec SecurityContextManager. J'utilise Ninject pour charger mon module de sécurité qui effectue cela au démarrage.
  6. Contexte par défaut utilisé si une autorisation ne spécifie pas SecurityContext, qui contient simplement les informations principales de la sécurité Asp.Net.
  7. Un SecurityService qui dispose d'un utilisateur, d'un SecurityContext et d'une autorisation, détermine tous les rôles que l'utilisateur a dans ce SecurityContext et vérifie si l'un quelconque des rôles a l'autorisation en cours de vérification.

À ce stade, voici un flux d'exemple dans Asp.Net MVC:

  • Recevez HttpRequest
  • via l'authentification par formulaire Authentifier
  • Route à Action Controller
  • si (Permission.GetByName ("CanDoSomething"). IsAllowed()) {// procéder

- [ A l'intérieur Permission.IsAllowed] -

  • SecurityService reçoit SecurityContext
  • Trouver SecurityContextValidator pour SecurityContext spécifié
  • globale tous les rôles statiques et dynamiques de SecurityContextValidator
  • itérer sur les rôles et vérifier si l'un d'entre eux ont la permission d'être demandé.
  • Retourne vrai ou faux!

Pour faciliter les choses, je l'ai pris un peu plus loin et a créé un AbstractContextProtectedAttribute, qui attend un délégué SecurityContextFactory qui peut créer un SecurityContext (donné une HTTPRequest, par exemple) et une autorisation de vérifier avec le SecurityContext spécifié.Les sous-classes de cette classe peuvent ensuite être utilisées pour décorer les actions du contrôleur.

Ouf! Donc, tout ce qui me permet maintenant de configurer une table des utilisateurs, des rôles, des autorisations et les mapper les uns aux autres, définissez toutes les autorisations dans la base de données. J'ai écrit un SecurityPersistenceService enfichable qui rend le cadre de sécurité agnostique de la stratégie de persistance utilisée - nous avons malheureusement tout de DataReaders, DataAdapters à Linq2Sql et EF. Mais au moins nous pouvons écrire le code comme ceci:

[Protected("CanAccessX")] // Checks using default context 
public class SomeController 
{ 
    [Protected("CanSeeY")] // Checks using default context 
    public PartialViewResult GetY(<parameters>) 
    { 
     var canSeeY_Variation1 = Permission.Get("CanSeeY_Variation1") ; 
     var y_Variation1_Context = new Y_Variation1_Context { <build your context here> } ; 
     if (canSeeY_Variation1.IsAllowed(y_variation1_Context)) 
     { 
      <return variation 1 view> 
     } 

     // Y_Variation_2...etc 
    } 
} 

Et pour faire ce travail, au démarrage, j'inscrire les validateurs appropriés:

public class MyNinjectModule 
{ 
    public override void Load() 
    { 
     // Wire up a persistence service for the security framework 
     // to use. 
     SecurityService.SecurityPersistenceService = new MySecurityPersistenceServiceImplementation() ; 

     // This is what allows the SecurityService to figure out what Validator to use 
     // in a specified Context to get the User's Roles.   
     SecurityService.RegisterValidator<Y_Variation1_Context>(new Y_Variation1_ContextValidator(...)) ; 
    } 
} 

Je travaille maintenant sur un ajout à ce cadre que nous allons J'effectue ces contrôles sur des énumérables de données, infusant ainsi tous les objets de mon domaine avec l'infrastructure de sécurité. Le seul moyen propre que je connaisse de faire cela est d'utiliser AOP. J'avais l'habitude de travailler en Java et utilisé AspectJ. Maintenant, je considère PostSharp.

Espérons que ceci fournit une perspective pour penser à votre problème.

+0

Aussi, je vous encourage à regarder l'architecture de gestion d'identité du framework Kuali Rice: http: // www. kuali.org/rice C'est Java, mais ils font de la sécurité au niveau des données dans une application web MVC, donc il y a quelques bonnes leçons là-bas. –

Questions connexes