Search code examples
c#asp.net.netasp.net-mvcfluent-security

How to redirect to specific page in FluentSecurity?


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 ?


Solution

  • 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>();
                            });
                    });
            }
        }