使用服务器端 Blazor,在连接到 SQL Server 数据库时如何使用 Windows 身份验证模拟用户?

Posted

技术标签:

【中文标题】使用服务器端 Blazor,在连接到 SQL Server 数据库时如何使用 Windows 身份验证模拟用户?【英文标题】:Using Server side Blazor, how do you impersonate a user using windows authentication when connecting to a SQL Server database? 【发布时间】:2021-11-05 13:30:28 【问题描述】:

我已经在我的数据库中设置了行级安全性,并且我正在尝试创建与数据库的连接。我在执行此操作时遇到问题,因为我似乎无法作为请求客户端向 SQL Server 发出请求。

应用程序是使用 Blazor 构建的,我的数据库连接是使用 EF Core 完成的。

用于在数据库上运行查询的服务器端方法如下

using System;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

public WeatherForecastService(IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IDbContextFactory<SqlDboDbContext> dbo)

        _httpContextAccessor = httpContextAccessor;
        _dbo = dbo;
        var context = _httpContextAccessor.HttpContext;
        Name1 = context.User.Identity.Name;

        WindowsIdentity.RunImpersonated(WindowsIdentity.GetCurrent().AccessToken, () =>
        
            Name2 = _httpContextAccessor.HttpContext.User.Identity.Name;
            var optionsBuilder = new DbContextOptionsBuilder<SqlDboDbContext>();
            optionsBuilder.UseSqlServer(configuration.GetConnectionString("SQL_Server"));
            using (var cntx = new SqlDboDbContext(optionsBuilder.Options))
            
                Markets = cntx.Markets.ToArray();
                t1 = cntx.Transactions.ToArray();
            
        );

Name1Name2 都显示客户端,但是当我查看在数据库上运行的查询时,使用

SELECT sdest.DatabaseName 
    ,sdes.session_id
    ,sdes.[host_name]
    ,sdes.[program_name]
    ,sdes.client_interface_name
    ,sdes.login_name
    ,sdes.original_login_name
    ,sdes.login_time
    ,sdes.nt_domain
    ,sdes.nt_user_name
    ,sdec.client_net_address
    ,sdec.local_net_address
    ,sdest.ObjName
    ,sdest.Query
FROM sys.dm_exec_sessions AS sdes
INNER JOIN sys.dm_exec_connections AS sdec ON sdec.session_id = sdes.session_id
CROSS APPLY (
    SELECT db_name(dbid) AS DatabaseName
        ,object_id(objectid) AS ObjName
        ,ISNULL((
                SELECT TEXT AS [processing-instruction(definition)]
                FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
                FOR XML PATH('')
                    ,TYPE
                ), '') AS Query

    FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
    ) sdest

--and sdes.nt_user_name = '' -- Put the username here !
ORDER BY sdec.session_id

所有字段都显示我为应用程序池设置的用户。

我尝试过的各种连接字符串:

"SQL_Server": "Data Source=[SQL server Address];Initial Catalog=Investment_Dev;Integrated Security=True;Trusted_Connection=true"

"SQL_Server": "Data Source=[SQL server Address];Initial Catalog=Investment_Dev;Integrated Security=SSPI;Trusted_Connection=true"

我的IIS配置如下

Authentication 中,所有设置为Disabled,但Windows Authentication 设置为Enabled

Configuration Editor -> system.webServer/security/authentication/windowsAuthentication 我已将useAppPoolCredentials 设置为False

对于我的网站Edit Site,我将Connect As 设置为Application user (pass-through authentication)

在我的应用程序池中,我将池 Managed pipeline mode 设置为 IntegratedIdentity 设置为我设置用于处理传入请求的服务帐户,Load User Profile 设置为 False 并且我'我试过把它设置为True

虽然我在上述方法中重新创建了一个新的dbcontext 来测试解决方案,但我的应用程序确实使用DbContextFactory 从数据库中获取数据。

Startup.cs我已经按照以下方式设置了。

using Impersonation_Test_Project.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    public void ConfigureServices(IServiceCollection services)
    
        services.AddRazorPages();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddDbContextFactory<SqlDboDbContext>(opt => opt
            .UseLazyLoadingProxies()
            
            .UseSqlServer(Configuration.GetConnectionString("SQL_Server")));
        services.AddHttpContextAccessor();
    

【问题讨论】:

以用户 X 的身份运行您网站的 IIS 应用程序池? 由于我的数据库设置了行级安全性,这不会只向所有连接用户显示一个用户特定的行而不是他们自己的行吗? 是的..我的错;我没有意识到您正在寻找该级别的身份验证 【参考方案1】:

Windows 身份验证并不意味着模拟。因此,通常您的代码作为您的应用程序池标识运行,这就是 WindowsIdentity.GetCurrent() 返回的内容。

参见例如ASP.NET Impersonation Authentication

您可以在没有模拟的情况下使用 SQL Server 行级安全性,如 here 所述。或者,您可以授予您的应用程序池身份特权以执行最终用户的 SQL Server 模拟,并在 SQL Server 中使用 EXECUTE AS 而不是在 Windows 中模拟他们。

【讨论】:

以上是关于使用服务器端 Blazor,在连接到 SQL Server 数据库时如何使用 Windows 身份验证模拟用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何在连接到局域网的其他电脑上使用SQL Server数据库运行桌面应用程序?

有没有办法使用 Easy 表在连接到 Azure App Service 的 iOS 应用程序中获取 SQL 数据库表

在连接到热点时通过 iPhone 连接到 localhost

Node 在连接到 Postgres 方面比 .NET Core 快 20 倍

Blazor MS SQL Server:用户登录失败/管道错误结束时没有进程

PHP Curl(带有 NSS)在连接到 https 时可能使用 SSLv3 而不是 TLS