【问题标题】:Custom IPrincipal Not Accessible in MVC5在 MVC5 中无法访问自定义 IPrincipal
【发布时间】:2015-10-19 17:21:40
【问题描述】:

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

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

这是一个使用 Windows 身份验证的 MVC 5 Web 应用程序(仅限 Intranet 应用程序)。我的自定义主体是WindowsPrincipal 的子类,我确实实现了自己的RoleProvider 以用于授权属性标签。

当我尝试通过在当前 HttpContext 上将其从 IPrincipal 强制转换为我的自定义主体来使用该主体时,我收到一条错误消息,指出它是 RolePrincipal 类型,显然无法将其强制转换为我的自定义主体。我在Application_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,但他们未能解决问题:

我做错了什么没有设置主体?如果需要发布更多代码,请告诉我。

编辑:在 WindowsAuthentication.OnAuthenticate 事件中将 HttpContext.Current.User 设置为我的自定义主体不能解决此问题。使用该方法表现出完全相同的行为。

【问题讨论】:

    标签: c# asp.net asp.net-mvc-5 asp.net-identity windows-authentication


    【解决方案1】:

    您应该在应用程序验证当前请求时发生的 WindowsAuthentication_OnAuthenticate 事件中设置自定义主体。

    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);
        }
    }
    

    【讨论】:

    • 使用WindowsAuthentication.OnAuthenticate 事件会表现出相同的行为。
    【解决方案2】:

    在不断研究这个问题后,我终于通过另一个 SO 问题找到了答案,使我的问题有点重复:MVC3 Windows Authentication override User.Identity

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

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

    不应使用 Application_AuthenticateRequest 事件,因为(HttpContext.Current.User 为空,即使 Windows 身份验证已打开)用户尚未在 Windows 身份验证过程中填充,因此我无法获取用户信息.

    Application_AuthorizeRequest 是链中的下一个,在引入 WindowsIdentity 之后发生。

    protected void Application_AuthorizeRequest(object sender, EventArgs e)
    {
        if (User.Identity.IsAuthenticated && Roles.Enabled)
        {
            Context.User = new CustomPrincipal((WindowsIdentity)User.Identity);
        }
    }
    

    选项 2:覆盖 AuthorizeAttribute

    这里是授权属性的覆盖

    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;
        } 
    }
    

    然后将所有 AuthorizeAttributes 替换为自定义版本。

    选项 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;
            }
        }            
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 2011-01-09
      • 1970-01-01
      • 2012-05-31
      相关资源
      最近更新 更多