C# Asp.Net核心Intranet Windows Identity应用程序中的模拟中间件

C# Asp.Net核心Intranet Windows Identity应用程序中的模拟中间件,c#,entity-framework,asp.net-core,impersonation,windows-identity,C#,Entity Framework,Asp.net Core,Impersonation,Windows Identity,在我解释我的问题之前,以下是我们的场景: 场景 我们只为内部网Windows用户编写软件(目前由本地Active Directory管理,但将来可能迁移到Azure AD) 到目前为止,有一个旧的单片Winforms应用程序,它使用数据集直接与数据库通信。所有对数据库的请求都是通过WindowsIdentity(最终用户上下文)进行的,因此数据库知道最终用户 对于未来的开发,我们希望使用Web API进行业务逻辑。只有web应用程序才能使用实体框架访问数据库。我们用ASP.NET核心(无状态)编

在我解释我的问题之前,以下是我们的场景:

场景

我们只为内部网Windows用户编写软件(目前由本地Active Directory管理,但将来可能迁移到Azure AD)

到目前为止,有一个旧的单片Winforms应用程序,它使用数据集直接与数据库通信。所有对数据库的请求都是通过
WindowsIdentity
(最终用户上下文)进行的,因此数据库知道最终用户

对于未来的开发,我们希望使用Web API进行业务逻辑。只有web应用程序才能使用实体框架访问数据库。我们用ASP.NET核心(无状态)编写了一个Web API,它托管在IIS中。因为web应用程序在应用程序池标识中运行,所以我们编写了一个中间件,向最终用户模拟上下文(以便数据库访问正常)

在迁移到web服务器时,必须支持两个版本,因为我们不能一次迁移整个应用程序

问题

在调试环境中,web服务器工作正常(因为没有模拟),但在实时系统上,有时服务器崩溃(不是每次)

我们遇到的最常见错误是
FileLoadException
,它无法加载dll(主要是
System.Reflection
)。其他时候,整个服务器运行时没有错误,返回200 OK,但不包含任何http正文

看来有个问题。文档对此有一个小提示:

因此,在用户上下文中运行整个请求似乎是个坏主意,但这可能是解决方案吗

当然,我们必须放弃的只是模拟中间件。但是如何访问数据库呢

选项#1:运行模拟的每个数据库调用

问题

官方文档说模拟上下文中的代码被禁止运行异步的东西。我们可以做到,没问题。但我不知道实体框架是否运行异步部分?如果发生这种情况,我们的应用程序可能会再次崩溃。你知道吗

问题2

如果两个请求传入,asp将运行两个线程。是否允许在某个时间对两个请求调用异步模拟?官方文件不是很清楚

选项#2:更改我们的数据库,以便不需要最终用户

问题

一些SQL触发器(和存储的或存储的)使用用户名进行插入,例如,在插入时将用户名写入表中。当然,我们可以改变这种行为,让EF核心手工书写名称

这个问题更像是一个政治问题,我们需要找到为什么我们应该将工作解决方案从
WindowsIdentity
更改为
AppIdentity
。你有好的论据吗

选项3:你还有什么想法吗

我看不到更多的解决方案,也许你看到了


顺便说一下。以下是我们的模拟中间件的代码:

公共类ImpersonateMiddleware
{
private readonly RequestDelegate\u next;
公共ImpersonateMiddleware(RequestDelegate下一步)
{
_下一个=下一个;
}
公共异步任务调用(HttpContext上下文)
{
var winIdent=context?.User?.Identity作为WindowsIdentity;
if(winIdent==null)
{
wait _next.Invoke(上下文).configurewait(true);
}
其他的
{
等待WindowsIdentity.RunImpersonated(WinIdentit.AccessToken,异步()=>
{
wait_next.Invoke(上下文)
.ConfigureAwait(true)
;
}).配置等待(true);
}
}
}
1.1问题:官方文档说模拟上下文中的代码禁止运行异步内容。我们可以做到,没问题。但我不知道EntityFramework是否运行异步部分?如果发生这种情况,我们的应用程序可能会再次崩溃。你知道吗

实际上,我认为这部分文档已经过时和/或错误。之前有人请求对
RunImpersonated
执行异步重载,并提到传递异步函数可以正常工作,因为模拟将在内部使用异步本地

所以你可以用它来表现得非常明确,或者继续使用它,因为这实际上是在做同样的事情。文档也明确允许将其用于异步工作:

此方法可以可靠地与异步/等待模式一起使用,这与模拟不同。在异步方法中,此方法的泛型重载可与异步委托参数一起使用,以便等待生成的任务

我认为ASP.NET核心文档在这方面已经过时,因此需要对其进行更正或澄清

运行整个模拟请求也应该可以正常工作,因此,除非我在该问题中听到其他消息,否则我会假设您在应用程序中看到的崩溃可能有不同于模拟的原因。我建议您首先尝试使用不同的(非开发)环境(有模拟和没有模拟)来分别复制这一点,以查看这是否确实与模拟相关。FileLoadException至少听起来不像是模拟的问题,只是被模拟的用户可能无法访问某些延迟加载的程序集(我不确定模拟是否会在此处产生影响)


1.2问题:如果两个请求传入,asp将运行两个线程。是否允许在某个时间对两个请求调用异步模拟?官方文件不是很清楚

由于模拟是使用异步本地调用实现的,因此模拟仅限于单个本地调用流。所以一个不同的请求,使用dif