如何在.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仪表板执行,就能在授权方法中获取到存储的上下文。
具体实现步骤:
- 共享AsyncLocalStorage类:将
AsyncLocalStorage类移至.NET Standard类库中,或者让类库引用包含该类的程序集,确保类库能调用其Get()方法。 - 保证中间件执行顺序:在应用启动代码中,确保
OwinContextMiddleware的注册在UseHangfireDashboard之前,这样请求会先经过中间件存储上下文,再进入Hangfire的授权逻辑。 - 在授权过滤器中获取上下文:在
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
相关产品推荐
相关产品推荐

