What's the best way to protect all actions fro

2019-04-10 15:09发布

问题:

Currently I have [Authorize] attributes on all of the methods on my AdminController except for the Logon action.

What's the cleanest way to invert this, so I don't have to remember to add the attributes to all methods, but rather add an attribute only to the method(s) that should be available without being logged in?

Would I be better just moving the Logon action to its own controller, and applying the [Authorize] attribute to the AdminController class?

回答1:

In ASP.NET MVC 3 you could implement a custom global action filter provider:

public class MyProvider : IFilterProvider
{
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        var rd = controllerContext.RouteData;
        var controller = rd.GetRequiredString("controller");
        if (string.Equals("admin", controller, StringComparison.OrdinalIgnoreCase) &&
            string.Equals("logon", actionDescriptor.ActionName))
        {
            return Enumerable.Empty<Filter>();
        }

        return new[]
        {
            new Filter(new AuthorizeAttribute(), FilterScope.Action, 0)
        };
    }
}

which could be registered in Application_Start:

FilterProviders.Providers.Add(new MyProvider());

Now if you are using some DI container such as NInject for example it supports filter binding syntax meaning that you could configure the kernel to inject the filter dynamically based on the context.

The pros of this approach is that now nomatter what controller or action is being added to your application => it will require authorization.



回答2:

I would, as you suggested, move the Logon action to its own controller and apply the [Authorize] attribute to entire AdminController class. This is cleaner and will be easier to maintain in the future.



回答3:

Another way that you can do this with the <location> element in the web.config. Here's an example:

  <location path="/Admin/LogOn">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>  

  <location path="/Admin">
    <system.web>
      <authorization>
        <allow users="?" />
        <deny users="*" />
      </authorization>
    </system.web>
  </location>


回答4:

I usually do something like this:

[Authorize]
public abstract class AdminController : Controller
{
}

And inherit from that w/a naming convention:

public class UserAdminController : AdminController 
{
}

vs:

public class UserController : Controller 
{
}


回答5:

You can do this using Filter Providers.

Phill Haack wrote about it here