Hi I'm using FluentSecurity to authenticate and verify users permissions in my MVC application. In the basic settings when a user wants to access to denied Action
it throws an exception. I want to know how should I redirect to another page (such as login page) instead of showing yellow exception page ?
I know this question has been answered already but I don't like putting a try catch in every action to handle this situation.
Fluent Security allows you to register a handler for policy violations (see https://github.com/kristofferahl/FluentSecurity/wiki/Policy-violation-handlers). You have to have a class that inherits from IPolicyViolationHandler. The convention is to name your class <PolicyViolationName>PolicyViolationHandler
Here is an example of a Handler to register a DenyAnonymousAccessPolicyViolationHandler
/// <summary>
/// Custom Policy Violation Handler. See http://www.fluentsecurity.net/wiki/Policy-violation-handlers
/// </summary>
public class DenyAnonymousAccessPolicyViolationHandler : IPolicyViolationHandler
{
public ActionResult Handle(PolicyViolationException exception)
{
Flash.Error("You must first login to access that page");
return new RedirectResult("/");
}
}
One other caveat that you will run into is that you have to use an IOC container to register these handlers. I won't debate whether using and IOC container is good or bad but I prefer not to use on if I don't have too. On their website there was a blog written on how to do this without using an IOC container but I didn't really like that approach as well. Here is what I did.
public static class SecurityConfig
{
public static void Configure()
{
SecurityConfigurator.Configure(c =>
{
c.GetAuthenticationStatusFrom(() => HttpContext.Current.User.Identity.IsAuthenticated);
c.GetRolesFrom(() => (HttpContext.Current.Session["Roles"] as string[]));
// Blanked Deny All
c.ForAllControllers().DenyAnonymousAccess();
// Publicly Accessible Areas
c.For<LoginController>().Ignore();
// This is the part for finding all of the classes that inherit
// from IPolicyViolationHandler so you don't have to use an IOC
// Container.
c.ResolveServicesUsing(type =>
{
if (type == typeof (IPolicyViolationHandler))
{
var types = Assembly
.GetAssembly(typeof(MvcApplication))
.GetTypes()
.Where(x => typeof(IPolicyViolationHandler).IsAssignableFrom(x)).ToList();
var handlers = types.Select(t => Activator.CreateInstance(t) as IPolicyViolationHandler).ToList();
return handlers;
}
return Enumerable.Empty<object>();
});
});
}
}