8

I know in MVC at the top of a controller you can use the [Authorize()] attribute to restrict access to that entire controller to certain authenticated users and/or roles, but not by IP, but this must be done on a per controller instance. Is there a way to restrict access to an entire MVC Area to an authenticated User/Role or by the request Source IP?

  • search for **Custom Authorize Attribute** – Dmitry Efimenko Aug 05 '13 at 17:04
  • I am not looking to create my own attributes. I just want to take the built in Role/User authorization controls and apply them at an Area level. It would also be nice if I could apply some code check for IPs at the area level, I know I could make a .cs file and call it from each controller action but that is a bit tedious. –  Aug 05 '13 at 17:09
  • 1
    what "built in Role/User authorization controls" do you have in mind? I can't think of any but the `[Authorize]` attribute. You could have a base controller for your area, have all controllers in that area derive from that base controller and slap that custom authorize attribute on the base controller. That would take care of the whole area authorization and you could customize it to restrict by IP – Dmitry Efimenko Aug 05 '13 at 17:19
  • I was talking about the built in ASP.Net membership and roles providers. When I looked up Custom Authorize Attribute it seemed to mostly revolve around Adapting it to a custom provider. I did not think about making a base controller to derive from, I think that would work out perfectly. If you want to make an answer of that I will mark it as my solution. –  Aug 05 '13 at 17:32
  • notice I updated ip address logic in the accepted ansswer. Also, I didn't test the code, so bugs are possible. – Dmitry Efimenko Aug 05 '13 at 18:13

1 Answers1

16

Create a Base Controller in your area:

[AuthorizeArea(AllowIpAddresses = new [] {"1.1.1.1", "1.2.3.4"})]
public class CustomAreaBaseController : Controller
{
    public CustomAreaBaseController()
    {
        // possibly any other common code that you want to run for all controllers in this area
    }
}

Have all controllers in your area derive from base controller:

public class HomeController : CustomAreaBaseController
{
    // actions for this controller
}

Create custom Authorize Attribute:

public class AuthorizeArea : AuthorizeAttribute
{
    public string[] AllowIpAddresses { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool isValid = false;

        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        // get current ip address
        var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
        if (string.IsNullOrEmpty(ipAddress))
            ipAddress = httpContext.Request.ServerVariables["remote_host"];

        if (AllowIpAddresses.Contains(ipAddress)) isValid = true;

        return base.AuthorizeCore(httpContext) && isValid;
    }
}
Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79