使用实体框架 ASP.NET 核心应用程序中远程用户的 Windows 身份验证



Background

我有一个在 Http.sys 中运行的 ASP.NET Core 应用程序来提供 Windows 身份验证。

我的应用程序的客户端使用 Windows 身份验证,首次访问站点时,系统会提示用户输入其 Windows 登录凭据。一切都很好。

我正在使用一个SQL Server数据库(与应用程序托管在同一服务器上),该数据库由实体框架使用代码优先方法构建。在startup.cs文件中,我正在运行一个dbContext.migrate()以确保数据库是最新的,然后应用程序继续正常运行。

问题

当远程用户与站点交互并执行需要数据库访问的操作时,我希望以他们的用户名执行该数据库事务。

例如,如果我以User1身份在我的服务器上运行 Asp.net 核心应用程序,然后从以User2身份登录的用户的计算机访问 Web 应用程序,则数据库交互仍由User1执行,因为这是运行主应用程序的用户。

我希望在这种情况下,可以通过User2而不是User1来执行数据库交互。主要用于记录和分析。

检索dbContext实例时,我为其提供了一个连接字符串,该字符串声明使用 SSPI 进行身份验证。有没有办法将远程用户的用户名包含到此连接中,以便他们以自己的身份连接到数据库?我可以轻松地从控制器中检索远程用户的凭据/用户名。我相信我可以使用称为Impersonation的东西,但我不确定实现它的最佳实践,或者它是否是推荐的解决方案。

任何帮助将不胜感激。

更新

感谢一些有用的反馈,我尝试实现以下内容:

我的连接字符串在startup.cs中设置如下:

services.AddDbContext<MyDbContext>(options => options.UseSqlServer(@"Server=MyServerMSSQLSERVER;Database=MyDatabase;Trusted_Connection=True;"));

然后,我在控制器/类中执行如下操作:

var values = new List<Values>();
WindowsIdentity.RunImpersonated(user.AccessToken, () =>
{
var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
optionsBuilder.UseSqlServer(@"Server=MyServerMSSQLSERVER;Database=MyDatabase;Trusted_Connection=True;");
using (var ctx = new MyDbContext(optionsBuilder.Options))
{
values = (from row in ctx.Table select row).OrderBy(x => x.Id).ToList();
}
});

user变量被传递到函数中,类型为WindowsIdentity

从本地主机执行代码工作正常,但是当远程用户尝试时,它会返回以下错误:System.Data.SqlClient.SqlException: 'A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - No such host is known.)

更新 2

我设法通过使用连接字符串的 IP 地址而不是服务器/计算机名称来解决此错误。所以现在我的连接字符串如下所示:@"Server=<IP address>MSSQLSERVER;Database=ConfigDb;Trusted_Connection=True

现在我面临另一个问题,SQL Server指出No connection could be made because the target machine actively refused it.我可以通过 SQL Management Studio 使用此用户连接到 SQL Server,但不能通过我的应用程序。

我在事件查看器中发现实际错误与SSPI有关:SSPI handshake failed with error code 0x8009030c, state 14 while establishing a connection with integrated security; the connection has been closed. Reason: AcceptSecurityContext failed. The operating system error code indicates the cause of failure. The logon attempt failed [CLIENT: <named pipe>]。不太确定为什么这会失败。

ASP.NET 核心文档涵盖了这个确切的主题。

简而言之,ASP.NET 核心不实现模拟。 它有一个使用WindowsIdentity的解决方法示例,但它有其局限性,应仅用于相对简单的操作。

还有一个NuGet包,可以帮助您获得更多功能,但仍然受到限制。

有没有办法将远程用户的用户名包含到此连接中,以便他们以自己的身份连接到数据库?

它不适用于仅提供连接字符串的用户名,您还需要当前用户的密码。

我相信我可以使用称为模拟的东西,但我不确定 实施该目标的最佳做法,或者是否推荐 溶液。

对于RunImpersonated,请按照以下步骤操作:

  • 使用 Windows 凭据而不是用户名和密码配置连接字符串。

    services.AddDbContext<IISWindowsDbContext>(options =>options.UseSqlServer(@"Server=localhostMSSQLSERVER01;Database=IISWindows;Trusted_Connection=True;"));
    
  • 用途

    public IActionResult About()
    {
    IList<Blog> blogs = new List<Blog>();
    var user = (WindowsIdentity)User.Identity;
    WindowsIdentity.RunImpersonated(user.AccessToken, () =>
    {
    var impersonatedUser = WindowsIdentity.GetCurrent();
    blogs = _context.Blogs.ToList();
    });
    return Ok(blogs);
    }
    

相关内容

  • 没有找到相关文章

最新更新