web-dev-qa-db-fra.com

Comment implémenter l'attribut Authorize personnalisé pour le cas suivant?

donc j'ai ma méthode d'action

[Authorize(Roles="Admin")]
public ActionResult EditPosts(int id)
{
    return View();
}

Dans mon cas, je dois autoriser les administrateurs afin qu'ils puissent modifier les messages mais (voici la partie cool), je dois également permettre au créateur du message de pouvoir modifier le message qui est un utilisateur normal. Alors, comment puis-je filtrer l'utilisateur qui a créé le message ainsi que les administrateurs, mais laisser les autres non autorisés? Je reçois l'ID PostEntry en tant que paramètre de route, mais après l'attribut et les attributs n'acceptent que des paramètres constants, cela ressemble à quelque chose de très difficile, vos réponses sont très appréciées, Cheers!

31
Freeman

Vous pouvez écrire un attribut d'autorisation personnalisé:

public class AuthorizeAdminOrOwnerOfPostAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            // The user is not authenticated
            return false;
        }

        var user = httpContext.User;
        if (user.IsInRole("Admin"))
        {
            // Administrator => let him in
            return true;
        }

        var rd = httpContext.Request.RequestContext.RouteData;
        var id = rd.Values["id"] as string;
        if (string.IsNullOrEmpty(id))
        {
            // No id was specified => we do not allow access
            return false;
        }

        return IsOwnerOfPost(user.Identity.Name, id);
    }

    private bool IsOwnerOfPost(string username, string postId)
    {
        // TODO: you know what to do here
        throw new NotImplementedException();
    }
}

puis décorez l'action de votre contrôleur avec:

[AuthorizeAdminOrOwnerOfPost]
public ActionResult EditPosts(int id)
{
    return View();
}
59
Darin Dimitrov

Je comprends que vous avez déjà accepté une réponse, et celle-ci a été publiée il y a quelque temps.

Si vous utilisez cet attribut une fois. Sur une méthode unique. Ce n'est pas une bonne implémentation. Au lieu de cela, vous devriez avoir:

[Authorize]   // Just make sure they are auth'ed at all.
public ActionResult EditPosts(int id)
{
    Post SomePost = findPostByID (id);   // However you do it - single lookup of post

    if (!user.IsInRole("Admin") &&  !{IsOwnerOfPost(post)} )  Return Not Authorized

  ... Edit post code here
}

Cela présente les avantages de:

  1. Pas de cours supplémentaire pour que quelqu'un se demande plus tard où il est utilisé.
  2. Aucune classe qui n'est utilisable nulle part ailleurs (vous n'obtenez pas de réutilisation avec un attribut personnalisé)
  3. Les performances sont meilleures: récupération unique du message
  4. Beaucoup plus facile pour quelqu'un de lire/comprendre comment cela fonctionne. Pas de code magique à retrouver.
  5. Et des années plus tard, lorsque la classe HttpContextBase n'existe pas ou que d'autres parties des astuces utilisées pour récupérer le paramètre Id ont disparu, le code fonctionne toujours ...
6
Traderhut Games