Préambule: c'est un peu une question philosophique. Je suis à la recherche de plus pour la "bonne" façon de faire plutôt que de "une" façon de le faire.
Imaginons que j'ai quelques produits, et un ASP.NET application MVC effectuer CRUD sur ces produits:-
mysite.example/products/1
mysite.example/products/1/edit
Je suis en utilisant le modèle de référentiel, de sorte qu'il n'a pas d'importance où ces produits proviennent:-de
public interface IProductRepository
{
IEnumberable<Product> GetProducts();
....
}
Aussi mon Référentiel décrit une liste d'Utilisateurs, et les produits dans lesquels ils sont des gestionnaires pour (beaucoup-beaucoup d'entre les Utilisateurs et les Produits). Ailleurs dans la demande, un Super-Admin consiste à effectuer des opérations CRUD sur les Utilisateurs et la gestion de la relation entre les Utilisateurs et les Produits qu'ils sont autorisés à gérer.
Personne n'est autorisé à afficher n'importe quel produit, mais seuls les utilisateurs qui sont désignés comme des "admins" pour un produit particulier sont autorisés à invoquer par exemple, l'action d'Édition.
Comment doit - je aller sur la mise en œuvre que dans ASP.NET MVC? À moins que j'ai raté quelque chose, je ne peux pas utiliser le haut-ASP.NET Autoriser en tant qu'attribut d'abord, j'avais besoin d'un rôle différent pour chaque produit, et la deuxième je ne sais pas quel rôle pour vérifier jusqu'à ce que j'ai récupéré mon Produit à partir du Référentiel.
Bien évidemment, on peut généraliser à partir de ce scénario à la plupart du contenu-scénarios de gestion - par exemple, les Utilisateurs sont autorisés à modifier leurs propres Messages du Forum. StackOverflow les utilisateurs ne sont autorisés à modifier leurs propres questions, à moins qu'ils ai 2000 ou plus rep...
La solution la plus simple, comme un exemple, serait quelque chose comme:-
public class ProductsController
{
public ActionResult Edit(int id)
{
Product p = ProductRepository.GetProductById(id);
User u = UserService.GetUser(); // Gets the currently logged in user
if (ProductAdminService.UserIsAdminForProduct(u, p))
{
return View(p);
}
else
{
return RedirectToAction("AccessDenied");
}
}
}
Mes questions:
- Une partie de ce code devra être répété - imagine qu'il y a plusieurs opérations (mise à Jour, Supprimer, SetStock, l'Ordre, la CreateOffer) en fonction de l'Utilisateur-Produits de la relation. Vous devez copier-coller plusieurs fois.
- Ce n'est pas très testable - ce que vous avez à se moquer de mon compte quatre objets pour chaque test.
- Il ne semble pas vraiment comme le contrôleur de "travail" pour vérifier si l'utilisateur est autorisé à effectuer l'action. Je préfère de loin un plus enfichable (par exemple AOP grâce à des attributs) de la solution. Cependant, serait-ce nécessairement que vous avez à SÉLECTIONNER le produit deux fois (une fois dans le AuthorizationFilter, et de nouveau dans le Contrôleur)?
- Serait-il mieux de retourner une 403 si l'utilisateur n'est pas autorisé à faire cette demande? Si oui, comment pourrais-je aller sur le faire?
Je vais probablement garder cette mise à jour comme je l'ai trouver des idées moi-même, mais je suis très impatient d'entendre la vôtre!
Merci à l'avance!
Modifier
Juste pour ajouter un peu de détail ici. La question que je vais avoir, c'est que je veux la règle d'entreprise "Seuls les utilisateurs autorisés peuvent modifier les produits" à être contenues dans un seul et unique endroit. J'ai l'impression que le même code qui détermine si un utilisateur peut GET ou POST pour le Modifier l'action devrait également être chargé de déterminer si pour rendre le lien "Modifier" sur l'Index ou les Détails de ce point de vue. Peut-être que ce n'est pas possible/pas possible, mais j'ai l'impression que ça devrait être...
Edit 2
Le démarrage d'une prime sur celui-ci. J'ai reçu des bons et des réponses utiles, mais rien de ce que je me sens à l'aise "accepter". Gardez à l'esprit que je suis à la recherche d'un bien propre méthode pour garder la logique métier qui détermine si oui ou non le lien "Modifier" sur l'index de la vue sera affiché au même endroit, qui détermine si oui ou non une demande de Produits/Modifier/1 est autorisé ou non. J'aimerais garder la pollution dans ma méthode d'action pour une absoloute minimum. Idéalement, je suis à la recherche d'un attribut de base de la solution, mais j'accepte que, peut-être impossible.