【问题标题】:Controller User is null控制器用户为空
【发布时间】:2012-04-12 18:16:31
【问题描述】:

我对 MVC 还很陌生,并且很难让我的应用程序在我的登台网络服务器上运行。在我的本地机器和开发服务器上,它运行良好。

问题在于,在我的操作中,用户为空(在登台上,而不是在开发和本地上)。我用谷歌搜索了为什么用户会为空的原因,但一切似乎都涵盖了。奇怪的是它可以在两台服务器上完美运行。

这是我的代码...

在 Global.asax 中 使用 PostAcquireRequestState 我使用自定义主体覆盖主体,该主体包含存储在 Session 中的对象。因此 SessionHelper 将获取对象并将其添加到主体。然后将主体设置为 httpcontext 和线程。

public class MvcApplication : HttpApplication
{
    public MvcApplication()
    {
        PostAcquireRequestState += new EventHandler(MvcApplication_PostAcquireRequestState);
    }

    void MvcApplication_PostAcquireRequestState(object sender, EventArgs e)
    {
        if (Context.User is ICSPrincipal)
            return;

        var principal = new ICSPrincipal(new GenericIdentity(User.Identity.Name), SessionHelper.UserClaims);
        HttpContext.Current.User = principal;
        Thread.CurrentPrincipal = principal;
    }

    ...
}

在我的控制器中,我将检索存储在主体中的值。 但问题是我的登台服务器上的用户为空。 但是它可以在我的本地机器和我的开发服务器上运行。 开发服务器和暂存服务器运行相同版本的 IIS,并且都安装了 MVC3。

public class HomeController : Controller
{
   public ActionResult Index()
   {
        //PROBLEM!!! User is NULL on staging server.
        var userClaims = ((ICSPrincipal)User).UserClaims;
        ...
   }
}

有没有人遇到过这个问题并解决了?我的印象是我可以在我的 Action 中安全地调用 User。

编辑:关于为什么我需要 SessionStorage 和自定义主体的情况草图。

我使用formsauthentication,因此涵盖了身份验证。但是,我曾经将一个包含额外用户数据(名字、姓氏;总共 6 个属性)的对象存储到来自身份验证 cookie 的用户数据中。 然而,在调查我的请求时,我发现每个请求(即使是图像)都超过 2.5KB。因此,我切换回仅将用户名存储在 cookie 中,并且在每个请求中,我希望从会话存储中完成数据。 这就是为什么我认为自定义主体会很棒。它从一个通用主体开始,一旦我们到达 Action,就会有一个自定义主体,其中包含我需要的所有数据来自我想要的任何地方(在这种情况下,来自 cookie 的用户名与来自会话的数据一起添加)。

我听到你说:但是,使用 Session 是不安全的,它会在一段时间后过期。我很清楚这一点,这就是为什么 SessionHelper 当然有一些智能。如果 Session 对象为空,它将根据经过身份验证的用户的用户名获取所需的所有数据。它将这些数据存储在 Session 中,因此后续请求不会查询我的数据库。

我还使用 API 通信(http 或命名管道),这就是为什么我需要自定义主体中的这些数据。我无法从该层访问 Session,但我可以访问主体。因此,如果在进行该通信之前更新了主体,则一切正常。

解决实际问题:

上述设置实际上在多台机器上都可以正常工作,但在与我的开发服务器设置相同的登台服务器上却不行。 在我的操作中分阶段投诉用户为空。我什至不知道这怎么可能。

【问题讨论】:

  • 您的登台服务器是否在不同的域中?
  • 是的,整个登台环境使用自己的服务器托管在不同的域上(都在同一个域中)。
  • 我刚刚发布到生产环境,我遇到了与暂存相同的问题。所以比分是2-2。本地和开发工作(在同一个域上),登台和生产不在(也在同一个域上,但与开发和本地不同)。
  • 似乎域可能与它有关。此外,您可能应该检查这两种情况下网站的配置方式,尤其是在管道模式、身份验证和其他可能启用的模块方面。
  • support.microsoft.com/kb/980368/en 似乎已经解决了这个问题。应用此补丁后,ASP.NET 4 应用程序可以处理对无扩展名 URL 的请求。因此,在处理程序执行之前运行的托管 HttpModules 将运行。在某些情况下,HttpModules 可能会返回无扩展 URL 的错误。例如,编写为仅预期 .aspx 请求的 HttpModule 现在在尝试访问 HttpContext.Session 属性时可能会返回错误。

标签: asp.net-mvc asp.net-mvc-3 model-view-controller controller httpcontext


【解决方案1】:

PostAcquireRequestState 是一个奇怪的地方。您应该在 AuthenticateRequest 中执行此操作。您还应该设置 Context.User 而不是 HttpContext.Current.User。

【讨论】:

  • 问题是用户在 AuthenticateRequest 中还不知道。可以使用 PostAuthenticateRequest,但是直到 PostAcquireRequestState 才知道 Session,因此我使用了这个事件。这个想法是我使用 Session 将用户数据存储在服务器上,而不是将其存储在客户端上并在每个请求上使用 cookie 传递它。
  • @GuillaumeSchuermans - 使用会话是个坏主意,因为会话可能随时消失。 IIS 可以随时回收会话,因此您需要能够从以其他形式(例如 cookie)存储的信息重建会话。事实上,MVC 将 Context 包装在一个可测试的包装器中,因此在建立此包装器之后设置 HttpContext.* 值可能会很棘手。
  • @GuillaumeSchuermans - 我很困惑。你怎么不知道 AuthenticateRequest 中的用户是谁?如果您正在执行自定义身份验证,则可以在此处进行身份验证。
  • 有效备注。这让我意识到我的情况草图并不完整。我将编辑原始问题,因为此文本框中没有足够的字符。
  • 好的,已编辑。我希望一切都清楚,因为我真的可以使用您的帮助,并且很高兴听到您的见解。
【解决方案2】:

http://support.microsoft.com/kb/980368/en

应用此补丁后,ASP.NET 4 应用程序可以处理对无扩展名 URL 的请求。因此,在处理程序执行之前运行的托管 HttpModules 将运行。在某些情况下,HttpModules 可以返回无扩展 URL 的错误。例如,编写为仅预期 .aspx 请求的 HttpModule 现在在尝试访问 HttpContext.Session 属性时可能会返回错误。

这已经解决了这个问题!感谢大家让我尝试多种设置。这样我就想出了这个解决方案。

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多