C# 自定义IPrincipal在MVC5中不可访问

C# 自定义IPrincipal在MVC5中不可访问,c#,asp.net,asp.net-mvc-5,asp.net-identity,windows-authentication,C#,Asp.net,Asp.net Mvc 5,Asp.net Identity,Windows Authentication,我已经阅读了很多关于这个话题的问题和答案,但是没有一个能帮助我解决这个问题 我遇到的问题是HttpContext.Current.User或justUser属性的类型是RolePrincipal,而不是我的自定义主体 这是一个使用Windows身份验证的MVC 5 web应用程序(仅限intranet应用程序)。我的自定义主体是WindowsPrincipal的子类,我实现了自己的RoleProvider,用于Authorize属性标记 当我试图在当前HttpContext上通过从IPrinci

我已经阅读了很多关于这个话题的问题和答案,但是没有一个能帮助我解决这个问题

我遇到的问题是
HttpContext.Current.User
或just
User
属性的类型是
RolePrincipal
,而不是我的自定义主体

这是一个使用Windows身份验证的MVC 5 web应用程序(仅限intranet应用程序)。我的自定义主体是
WindowsPrincipal
的子类,我实现了自己的
RoleProvider
,用于Authorize属性标记

当我试图在当前HttpContext上通过从
IPrincipal
将主体强制转换为我的自定义主体来使用主体时,我得到一个错误,指出它属于RolePrincipal类型,这显然无法强制转换为我的自定义主体。我正在
应用程序\u PostAuthenticationRequest
事件中设置自定义主体:

protected void Application_PostAuthenticationRequest(object sender, EventArgs e)
{
    if (User == null)
        return;

    using(EntityContext db = new EntityContext ())
    {
        var user = db.Users.SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
        HttpContext.Current.User = new PcsPrincipal((WindowsIdentity)User.Identity, user);
    }
}
当我在该方法中设置断点时,它似乎从未被调用,这可能解释了为什么它没有设置为我的自定义主体

我已经审查了以下QA,但它们无法解决问题:

  • -在Global.asax.cs的Init方法中添加了事件处理程序的注册。似乎没有什么不同。另外,
    \u应用程序
    变量在MVC5中似乎无效
  • -在web.config文件中进行了更改,但这在运行时导致了各种错误,错误表明ASP.NET管道配置不正确
我做了什么不正确的没有主要集?如果需要发布更多代码,请告诉我


编辑:在WindowsAuthentication.OnAuthentication事件中将HttpContext.Current.User设置为我的自定义主体无法解决此问题。使用该方法会显示完全相同的行为。

您应该在WindowsAuthentication\u onAuthentication事件中设置自定义主体,该事件在应用程序验证当前请求时发生

protected void WindowsAuthentication_OnAuthenticate(object source, WindowsAuthenticationEventArgs e)
{   
    using(EntityContext db = new EntityContext ())
    {
        var user = db.Users.SingleOrDefault(u => u.ADName.Equals(e.Identity.Name));
        HttpContext.Current.User = new PcsPrincipal(e.Identity, user);
    }
}

在不断研究这一问题后,我最终通过另一个问题找到了答案,使我的问题有点重复:

下面是@Toby Jones发布的答案(作为对其原始问题的编辑),这导致我解决了我的问题,但他的答案实际上是@Erik Funkenbusch和@Darin Dimitrov发布的两个答案的总和。编辑答案是为了修正一些语法&删除一些多余的信息

选项1:覆盖Global.asax中的授权请求

不应使用Application_AuthenticateRequest事件,因为(
HttpContext.Current.User
为空,即使Windows身份验证处于启用状态),用户尚未在Windows身份验证过程中填充,因此我无法使用任何内容来获取用户信息

Application\u AuthorizeRequest
是该链中的下一个,在引入WindowsIdentity之后发生

protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
    if (User.Identity.IsAuthenticated && Roles.Enabled)
    {
        Context.User = new CustomPrincipal((WindowsIdentity)User.Identity);
    }
}
选项2:覆盖authorized属性

下面是Authorize属性的覆盖

public class CAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
            return false;

        IIdentity user = httpContext.User.Identity;
        CPrincipal cPrincipal = new CPrincipal(user);
        httpContext.User = cPrincipal;

        return true;
    } 
}
然后将所有属性替换为自定义版本

选项1全局处理所有内容,而选项2使用过滤器在更单独的级别处理所有内容

就个人而言,我选择使用global.asax方法,因此我的自定义主体可以在全球范围内使用。以下是解决我的问题的实际代码:

protected void Application_AuthorizeRequest(object source, EventArgs e)
{
    if(User.Identity.IsAuthenticated && Roles.Enabled)
    {
        using (EntityContext db = new EntityContext ())
        {
            var user = db.Users.Include("Roles").SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
            if (user == null)
                return;

        PcsPrincipal principal = new PcsPrincipal((WindowsIdentity)User.Identity, user);
            Context.User = principal;
        }
    }            
}

使用
WindowsAuthentication.onAuthentication
事件显示相同的行为。