Si vous lisez mon blog régulièrement, vous avez du vous rendre compte qu’ASP.NET MVC n’est pas vraiment terrible, puisque je passe mon temps à refaire tout ce qu’il fait déjà. Je continue aujourd’hui avec la gestion des droits d’accès aux pages.

ASP.NET MVC, tout comme les WebForms, se base sur les Membership providers pour la gestion des utilisateurs. Mais contrairement aux WebForms, on ne pourra pas utiliser le web.config pour définir quelles pages sont accessibles ; pour ça, MVC utilise les DataAnnotations sur les contrôleurs et les actions. On va décorer nos contrôleurs (ou nos actions) avec un petit [Authorize] pour définir que l’utilisateur doit être logué pour accéder au contrôleur (ou à l’action).

Pour donner les autorisations par utilisateur ou par rôle (groupes basés sur le Role Provider), on va pouvoir définir les utilisateurs et rôles autorisés. En pratique, ça donnera quelque chose comme ça :

[Authorize]
public ActionResult UserDetail()
{
	var userData = GetCurrentUserData();
	return View(userData);
}

[Authorize(Roles="Administrateurs", Users="Guigui")]
public ActionResult Admin()
{
	return View();
}

Voilà, c’est bien beau tout ça, mais comme j’ai dis en introduction, ça me suffit pas. Oui, je suis exigeant (qui a dit "chieur" ?), et moi ce que je veux, c’est pouvoir définir les droits dynamiquement. Par exemple, j’aurais dans ma base de données ma liste de contrôleurs, d’actions, et de rôles associés qui seraient autorisés à y accéder... et ça, ben je peux pas le faire avec le AuthorizeAttribute.

Qu’à celà ne tienne, je vais faire mon attribut à moi ! Et comme j’ai pas envie de tout refaire, je vais directement hériter du AuthorizeAttribute, et faire mes vérifications à la mimine. Pour les vérifications, j’aurai juste à redéfinir la méthode AuthorizeCore qui renverra true si l’utilisateur a accès, ou false s’il n’y a pas accès... Voilà le résultat :

public class MyDbAuthorizeAttribute : AuthorizeAttribute
{
	protected override bool AuthorizeCore(HttpContextBase httpContext)
	{
		MvcHandler handler = httpContext.CurrentHandler as MvcHandler;
		RouteValueDictionary routeValues = handler.RequestContext.RouteData.Values;

		String controller = routeValues["controller"].ToString();
		String action = routeValues["action"].ToString();
		IPrincipal user = httpContext.User;

		return CheckAuthorization(user, controller, action);
	}

	private bool CheckAuthorization(System.Security.Principal.IPrincipal iPrincipal, string controller, string action)
	{
		// Ici je vais pouvoir interroger ma base de données
		return true;
	}
}

Une fois qu’on a définit notre attribut, on n’a plus qu’à taguer tous nos contrôleurs avec un [MyDbAuthorize] pour que la vérification des droits se fasse dans notre méthode de vérification.