用于 Windows-Identity 的 Asp.Net Core Intranet 应用中的模拟中间件

如何解决用于 Windows-Identity 的 Asp.Net Core Intranet 应用中的模拟中间件

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

场景

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

到目前为止,还有一个旧的整体式 Winforms 应用程序,它使用数据集直接与数据库通信。对数据库的所有请求都发生在 WindowsIdentity(最终用户上下文)中,因此数据库知道最终用户。

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

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

问题

在调试环境中,Web 服务器工作正常(因为不会发生模拟),但在实时系统上,服务器有时会崩溃(并非每次都如此)。

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

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

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1#impersonation

enter image description here

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

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

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

问题

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

问题 2

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

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

问题

一些 SQL 触发器(和存储的 orocedures)使用用户名,例如在插入时将名称写入表中。当然,我们可以更改该行为,以便 EF Core 手动写入名称。

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

选项 #3:您还有其他想法吗?

我没有看到更多的解决方案,也许你有?


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

public class ImpersonateMiddleware
{
    private readonly RequestDelegate _next;

    public ImpersonateMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        var winIdent = context?.User?.Identity as WindowsIdentity;

        if (winIdent == null)
        {
            await _next.Invoke(context).ConfigureAwait(true);
        }
        else
        {
            await WindowsIdentity.RunImpersonated(winIdent.AccessToken,async () =>
            {
                await _next.Invoke(context)
                    .ConfigureAwait(true) 
                    ;
            }).ConfigureAwait(true);
        }
    }
}

解决方法

1.1 问题: 官方文档说模拟上下文中的代码禁止运行异步事物。我们可以做到,没问题。但我不知道 EntityFramework 是否运行异步部分?如果发生这种情况,我们的应用程序可能会再次崩溃。你有什么想法吗?

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

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

Impersonate 不同,此方法可以可靠地与 async/await 模式一起使用。在异步方法中,此方法的通用重载可以与异步委托参数一起使用,以便可以等待结果任务。

我相信 ASP.NET Core 文档在这方面已经过时了,opened an issue for this 需要对其进行更正或澄清。

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


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

由于模拟是使用异步本地实现的,因此模拟仅限于单个本地调用流程。因此,使用不同异步流的不同请求不会受到被模拟的另一个请求的影响。这也使模拟线程安全。


2.1 问题: 一些 SQL 触发器(和存储过程)使用用户名,例如在插入时将名称写入表中。当然,我们可以更改该行为,以便 EFCore 手动写入名称。

是的,将该用户名传递到您的查询中可能是可行的方法。

这个问题更像是一个政治问题,以找出我们应该将工作解决方案从 WindowsIdentity 更改为 AppIdentity 的原因。你有什么争论吗?

过去参与过一个项目,这也是一个要求,我可以说模仿数据库并没有真正说服我。为了使其工作,每个用户都需要被授权在数据库中进行更改。这也意味着通过直接访问数据库,用户可能会进行更改,而这些更改仅使用应用程序是不允许的。他们基本上可以绕过任何特定于应用程序的授权和保护。

当然,用户不应该能够直接连接到数据库,但这总是可能发生的。如果没有适当的保护措施,那么这会变得更加重要。还要考虑那些对您的机器具有管理员访问权限的人,例如那些正在开发应用程序的人。由于没有可以在数据库中进行更改的帐户,因此他们没有限制访问权限,默认情况下他们确实有访问权限,因为这就是应用程序的工作方式。

在这些情况下保护您的数据库比拥有有限数量且只有少数用户知道的有限访问权限要困难得多。

此外,由于您提到迁移到 Azure AD,为了让您的应用程序能够模拟,您的 AD 需要完全联合并且应用程序服务器需要成为域的一部分。所以你必须牢记这一点。

而且,由于您仍然依赖 Windows 身份验证,这也使身份验证变得更加复杂。用户必须连接到域控制器才能从 NTLM 中受益,否则他们每次都必须使用他们的帐户数据进行身份验证。您将无法切换到其他身份验证方式,例如使用 Azure AD 或 ADFS,这意味着您也不会从单点登录等功能中受益。

(注意:您可以使用 Windows 身份验证以外的其他方法,并让应用程序通过创建 Windows 身份本身来模拟用户。但是相信我,您不想这样做那个;这是一个配置噩梦)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res