You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Standard类库中访问.NET Framework应用的AsyncLocal存储OWIN上下文?

问题描述

我有一个被.NET 4.7.2应用引用的.NET Standard类库,在该应用中自定义了OWIN中间件,提取OWIN上下文并将其存入AsyncLocal<IOwinContext>变量。请问能否在类库中访问该上下文?

补充说明:.NET Standard类库中包含Hangfire仪表板授权逻辑,需要在Authorize()方法中获取OWIN上下文。

限制条件:

  • 类库目标框架为.NET Standard,无法在Authorize方法中使用new OwinContext(dashboardContext.GetOwinEnvironment())
  • .NET Standard中无法直接获取HttpContext
  • 尝试从Hangfire.AspNetCore中提取OWIN上下文,但因应用基于.NET Framework而报错,因此希望通过AsyncLocal共享上下文的方式解决。

现有代码如下:

应用中的自定义中间件及存储类

public class OwinContextMiddleware
{
    private readonly Func<IDictionary<string, object>, Task> _next;

    public OwinContextMiddleware(Func<IDictionary<string, object>, Task> next)
    {
        _next = next;
    }

    public async Task Invoke(IDictionary<string, object> environment)
    {
        // 捕获OWIN上下文
        var owinContext = new OwinContext(environment);

        // 将上下文存入AsyncLocal
        AsyncLocalStorage.Set(owinContext);

        await _next(environment);
    }
}

public static class AsyncLocalStorage
{
    private static readonly AsyncLocal<IOwinContext> _current = new AsyncLocal<IOwinContext>();

    public static void Set(IOwinContext context)
    {
        _current.Value = context;
    }

    public static IOwinContext Get()
    {
        return _current.Value;
    }
}

.NET Framework应用启动代码

app.Use(typeof(OwinContextMiddleware));
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
    Authorization = new[] {
            new DashboardAuthorization() 
            // 相关代码
        }
});

.NET Standard类库中的Hangfire授权逻辑

public class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
    private readonly BasicAuthAuthorizationFilterOptions _options;

    public BasicAuthAuthorizationFilter(BasicAuthAuthorizationFilterOptions options)
    {
        _options = options;
    }

    public bool Authorize(DashboardContext context)
    {
        // 此处需要访问OWIN上下文
    }
}
解决方案

可以通过AsyncLocal在.NET Standard类库中访问到OWIN上下文,核心逻辑是AsyncLocal会在同一异步调用流中共享上下文数据,只要保证中间件先于Hangfire仪表板执行,就能在授权方法中获取到存储的上下文。

具体实现步骤:

  1. 共享AsyncLocalStorage类:将AsyncLocalStorage类移至.NET Standard类库中,或者让类库引用包含该类的程序集,确保类库能调用其Get()方法。
  2. 保证中间件执行顺序:在应用启动代码中,确保OwinContextMiddleware的注册在UseHangfireDashboard之前,这样请求会先经过中间件存储上下文,再进入Hangfire的授权逻辑。
  3. 在授权过滤器中获取上下文:在Authorize方法中直接调用AsyncLocalStorage.Get()即可拿到OWIN上下文。

修改后的授权过滤器代码:

public class MyAuthorizationFilter : IDashboardAuthorizationFilter
{
    private readonly BasicAuthAuthorizationFilterOptions _options;

    public MyAuthorizationFilter(BasicAuthAuthorizationFilterOptions options)
    {
        _options = options;
    }

    public bool Authorize(DashboardContext context)
    {
        // 获取存储的OWIN上下文
        var owinContext = AsyncLocalStorage.Get();
        
        // 基于上下文执行授权逻辑,例如检查用户身份
        if (owinContext?.Authentication?.User?.Identity?.IsAuthenticated == true)
        {
            // 授权通过逻辑
            return true;
        }

        // 授权拒绝逻辑
        return false;
    }
}

注意事项

  • 若请求未经过OwinContextMiddleware(比如Hangfire的后台作业触发的请求),AsyncLocalStorage.Get()会返回null,需要在代码中做空值判断。
  • AsyncLocal的上下文仅在当前异步调用流中有效,跨线程或独立的异步任务无法共享该上下文。

内容的提问来源于stack exchange,提问作者AZeus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:32:08