在ASP.NET MVC 3中注入IPrincipal - 我做错了什么?

时间:2012-05-08 23:28:57

标签: c# asp.net-mvc-3 razor ninject

我有一个自定义IIdentity实现:

public class FeedbkIdentity : IIdentity
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string Name { get; set; }

    public FeedbkIdentity() 
    {
        // Empty contructor for deserialization
    }

    public FeedbkIdentity(string name)
    {
        this.Name = name;
    }

    public string AuthenticationType
    {
        get { return "Custom"; }
    }

    public bool IsAuthenticated
    {
        get { return !string.IsNullOrEmpty(this.Name); }
    }
}

和自定义IPrincipal

public class FeedbkPrincipal : IPrincipal
{
    public IIdentity Identity { get; private set; }

    public FeedbkPrincipal(FeedbkIdentity customIdentity)
    {
        this.Identity = customIdentity;
    }

    public bool IsInRole(string role)
    {
        return true;
    }
}

在global.asax.cs中,我正在反序化FormsAuthenticationTicket userData并替换

HttpContext.Current.User:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        JavaScriptSerializer serializer = new JavaScriptSerializer();

        FeedbkIdentity identity = serializer.Deserialize<FeedbkIdentity>(authTicket.UserData);

        FeedbkPrincipal newUser = new FeedbkPrincipal(identity);
        HttpContext.Current.User = newUser;
    }
}

然后,在Razor Views中我可以做到:

@(((User as FeedbkPrincipal).Identity as FeedbkIdentity).FirstName) 

我已经在使用Ninject为成员资格提供程序注入自定义用户存储库,我一直在尝试将IPrincipal绑定到HttpContext.Current.User:

internal class NinjectBindings : NinjectModule
{
    public override void Load()
    {
        Bind<IUserRepository>().To<EFUserRepository>();
        Bind<IPrincipal>().ToMethod(ctx => ctx.Kernel.Get<RequestContext>().HttpContext.User).InRequestScope();
    }
}

但它不起作用。

我要做的就是能够访问我的自定义IIdentity属性,如下所示: @User.Identity.FirstName

我该如何使这项工作?

修改

我期望通过将IPrincipal绑定到HttpContext.Current.User,如下所示:MVC3 + Ninject: What is the proper way to inject the User IPrincipal?我将能够在我的应用程序中访问@User.Identity.FirstName

如果不是这样,那么将IPrincipal绑定到HttpContext.Current.User的目的是什么,如链接问题所示?

2 个答案:

答案 0 :(得分:3)

我建议您创建自己的基础WebViewPage。见http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx

然后你可以做到

public FeedbkPrincipal FeedbkPrincipal
{
    get
    {
        return User as FeedbkPrincipal;
    }
}

public FeedbkIdentity FeedbkIdentity
{
     get
     {
         return FeedbkPrincipal.Identity as FeedbkIdentity;
     }
}

然后就是

@FeedbkIdentity.FirstName
在视图中

  

将IPrincipal绑定到HttpContext.Current.User的目的是什么,如链接问题所示

依赖注入允许您在运行时选择组件。在给出的示例中,您可以执行

public MyClassConstructor(IPrincipal principal) { // }

和IPrincipal将自动绑定到用户。请注意,这不允许您访问特定的FeedbkPrincipal属性,因为即使在运行时它将变为类型FeedbkPrincipal,您的类也不知道。依赖注入不是当前问题的解决方案,因为您确实需要一种访问具体类的方法。

答案 1 :(得分:1)

假设HttpContext.User设置正确,您可以创建一个全局过滤器,以使用ViewBag自动填充FeedbkIdentity

E.g。

创建

public class FeedbkPrincipalIntoViewBagAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var principal = filterContext.HttpContext.User as FeedbkPrincipal;
        if (principal != null)
        {
            filterContext.Controller.ViewBag.Identity = principal.Identity as FeedbkIdentity;
        }
    }
}

注册

protected void Application_Start()
{
    GlobalFilters.Filters.Add(new FeedbkPrincipalIntoViewBagAttribute());
}

使用它

@ViewBag.Identity.FirstName