Custom Authorization MVC 3 and Ninject IoC

*爱你&永不变心* 提交于 2019-11-27 19:54:26
Remo Gloor

Attributes do not support constructor injection as they are created by the .NET Framework and are not under control of Ninject. If you really want to use a FilterAttribute (which I do not recommend) you'll have to use property injection.

Instead continue what you just began. You need a filter implementing IAuthorizationFilter (not derived from FilterAttribute, just remove it from your code above) and additionally an ordinary attribute to mark the controllers/actions.

Then change the binding:

this.BindFilter<MyAuthorizeFilter>(FilterScope.Controller, 0).WhenControllerHas<MyAuthorizeAttribute>();

See: https://github.com/ninject/ninject.web.mvc/wiki/MVC3

The problem with you current implementation is that it is found once as filter attribute and once added as normal filter. One for these instances will have the repo injected an the the repo is null for the other one.

NOTE: you can derive from an existing FilterAttribute if this simplifies your implementation. But do not use it as a attribute in this case but use it as an ordinary filter.

It is better to extend the AuthorizeAttribute class so that authorization works correctly with cached requests. You will also need to use Ninject.Web.Mvc

You will need to use Ninject property injection to use your repository. Constructor injection will not work with Attributes.

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    [Inject]
    public IMyRepo MyRepo { get; set; }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return base.AuthorizeCore(httpContext);
    }
}

Just thought that I would add my solution here as seems to work fine.

Created a class that extents AuthorizeAttribute and takes repository interface in constructor.

This class then overrides the AuthorizeCore function:

public class MyRoleAttribute : AuthorizeAttribute
{
    private ICRepository repository;

    public MyRoleAttribute(ICRepository Repo)
    {
        repository = Repo;
    }

protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //Check if user authenticated
        if (!httpContext.Request.IsAuthenticated)
            return false;

         //Can access items in the query string if needed
         var id = (httpContext.Request.RequestContext.RouteData.Values["id"] as string)
         ??(httpContext.Request["id"] as string);

          //Can access repository that has been injected
          if (repository.IsGroupCreator(.....))
            {

                return true;

            }
            else
            {

                return false;

            }
    }
}

Then for the repository injection to work I added the following code to the mvc NinjectWebCommon.cs file:

kernel.BindFilter<MyRoleAttribute>(FilterScope.Action, 0).When(
(controllerContext, actionDescriptor) => actionDescriptor.ActionName == "MyAction");

This then allows me to control what actions I need the attribute on and ninject takes care of the repository injection. Hope this helps someone.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!