2

我们有一个工作队列,用户可以向其中添加工作。添加工作项时,上下文是用户 ( HttpContext)。但它是一个后台线程,轮询队列并按顺序一一执行。

我不能只存储用户,因为当HttpContextPrincipal 对象被释放时

可以在 worker 中运行的代码需要 Principal 对诸如此类的东西是正确的PrincipalPermissions

此外,生命周期管理 (IoC) 使用HttpContextforInRequest范围,是否可以HttpContext使用正确的主体重新创建 a 等。

编辑: 伪造 HttpContext 只是一个很好的生命时间管理功能,我可以解决这个问题。但是我们的后端代码很大程度上依赖于线程的正确用户主体,因为我们使用它来验证用户是否可以访问系统的该部分。如果有人可以回答如何存储具有身份、角色和 IsAuthenticated 状态的用户主体,然​​后在另一个线程上使用它,我会标记为答案

4

3 回答 3

1

从 中使用有状态数据的最佳实践HttpContext是创建您自己的应用程序特定上下文,该上下文在构造函数中接受一个HttpContext(依赖注入)。

你的业务逻辑永远不应该依赖于一个HttpContext新的应用程序特定的上下文(可能是使用来自的信息创建的HttpContext)。

这不仅可以解决您的上述问题,还可以增加代码的可测试性。

例子:

public class MyApplicationContext
{
    public IPrincipal ContextPrincipal { get; set; }

    public MyApplicationContext(HttpContext httpContext)
    {
        // Store the current user principal & identity
        ContextPrincipal = httpContext.User;

        // Need to grab anything else from the HttpContext? Do it here! 
        // That could be cookies, Http request header values, query string 
        // parameters, session state variables, etc.
        //
        // Once you gather up any other stateful data, store it here in 
        // your application context object as the HttpRequest can't be passed 
        // to another thread.
    }

}

public class MyHttpHandler : IHttpHandler
{
    #region IHttpHandler Members

    public bool IsReusable
    {
        // Return false in case your Managed Handler cannot be reused for another request.
        // Usually this would be false in case you have some state information preserved per request.
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        // Do some work on another thread using the ThreadPool
        ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), new MyApplicationContext(context));
    }

    public void DoWork(object state)
    {
        // Grab our state info which should be an instance of an 
        // MyApplicationContext.
        MyApplicationContext context = (MyApplicationContext) state;

        // Assign this ThreadPool thread's current principal according 
        // to our passed in application context.
        Thread.CurrentPrincipal = context.ContextPrincipal;

        // Check if this user is authenticated.
        if (context.ContextPrincipal.Identity.IsAuthenticated)
        {
            var userName = context.ContextPrincipal.Identity.Name;
        }

        // Check if this user is an administrator.
        if (context.ContextPrincipal.IsInRole("Administrator"))
        {
        }

        // Do some long-ish process that we need to do on the threadpool 
        // after the HttpRequest has already been responded to earlier.
        //
        // This would normally be some fancy calculation/math, data 
        // operation or file routines.
        for (int i = 0; i < 30; i++)
        {
            Thread.Sleep(1000);
        }
    }

    #endregion
}

和接口都IPrincipal没有IIdentity明确提供 dispose 方法。所以他们都应该可以保留对他们的引用。但是,我没有测试过上面的代码,我只是为了这个问题而写的。

如果通过一些糟糕的设计,它们实际上确实依赖于底层数据库连接来查询角色成员资格,那么您只需在应用程序上下文的构造函数中更早地评估它,而 HttpContext 和 asp.net 表单身份验证提供程序仍然未处理/关闭。

您总是可以拆开主体和身份并重新创建一个新实例,GenericPrincipal甚至GenericIdentity创建您的应用程序身份类来实现IIdentity. 这里有很多定制/扩展的空间。

于 2013-06-03T05:20:45.793 回答
0

你为什么不使用辅助类来保存你需要的信息?您可以在 Web 请求期间使用适当的值创建它,并将其作为参数传递给后台工作人员。

由于内部服务器会话状态HTTPContext,无法克隆对象。即使有可能,在真正的 HTTP 请求之外使用它来检查值似乎也不是一个好的解决方案。

于 2013-05-30T10:54:15.323 回答
0
public void TestMethod1()
{
    System.Net.WebClient client = new System.Net.WebClient();
    client.BaseAddress = "http://www.teejoo.com";            

    //Invoke your function here
    client.OpenReadAsync(new Uri("http://www.teejoo.com/YourLogicalPage.aspx"));
    //Pur your logical in your page, so you can use httpContext 

    client.OpenReadCompleted += new System.Net.OpenReadCompletedEventHandler(client_OpenReadCompleted);
}

void client_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
{            
    //to Check the response HERE
}
于 2013-05-30T00:52:02.697 回答