How to protect an entire MVC Area by IP/Role/User?
Asked Answered
A

1

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?

Alloy answered 5/8, 2013 at 16:34 Comment(5)
search for Custom Authorize AttributeElwell
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.Alloy
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 IPElwell
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.Alloy
notice I updated ip address logic in the accepted ansswer. Also, I didn't test the code, so bugs are possible.Elwell
E
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;
    }
}
Elwell answered 5/8, 2013 at 18:3 Comment(2)
I like this approach. As an aside, what would you do if the IP addresses were stored in a database?Marna
You'd have to retrieve them from db inside this method and probably cache them.Elwell

© 2022 - 2024 — McMap. All rights reserved.