自承载Katana服务在SQL Server连接上实现模拟



我们使用Owin/Katana将我们的Web应用程序自托管为Windows服务。 HttpListener接受传入的连接并将其移交给 Owin 管道。

为了在 Web 前端实现集成身份验证,Windows 服务需要以NetworkSystemLocalSystem运行,因为这些是可以询问域控制器并验证用户凭据的唯一帐户。

Windows 服务还需要查询 SQL Server 数据库。但是,NetworkSystemLocalSystem都没有足够的权限连接到 SQL Server,因此我们需要在连接到数据库时模拟另一个域帐户。

为了实现这一点,我们尝试简单地实现我们自己的IDbConnection,该将在调用Open时模拟另一个用户,然后在Dispose上恢复该模拟,最终得到如下代码:

using (var conn = _connectionCreator.Create(_configuration.ConnectionString)) //this creates our own IDbConnection with impersonation built in
{
    using (var cmd = _commandCreator.Create("mysproc", CommandType.StoredProcedure))
    {
        conn.Open(); //here we switch to the user we're impersonating
        cmd.Connection = conn;
        //do the rest            
    }
} //call to Dispose here reverts the impersonation

我们遇到的问题是下面的调用抛出了一个类强制转换异常:

cmd.Connection = conn; //throws a cast exception

事实证明,如果您的cmd是类型 SqlCommand 它期望Connection对象是类型 SqlConnection .

我们不能扩展SqlConnection因为它是sealed.

有没有人遇到过在查询 SQL Server 时需要模拟?如果是这样,您是如何解决的(无需切换到 IIS 进行托管)?

如果其他人需要知道,我们最终通过实现我们自己的IDbConnectionIDbCommand版本来解决这个问题,分别包装SqlConnectionSqlCommand。实现两者绕过了强制转换异常,并允许我们添加模拟代码。

public class SqlImpersonatedConnection : DbConnection
{
    private readonly SqlConnection _connection; //SqlImpersonatedConnection calls into _connection, doing impersonation where required
    private readonly string _domain;
    private readonly string _username;
    private readonly string _password;
    private IImpersonationContext _impersonationContext;
    public SqlImpersonatedConnection(string connectionString, string domain, string username, string password)  
    {
        _domain = domain;
        _username = username;
        _password = password;
        _connection = new SqlConnection(connectionString);
    }
    //more stuff
 }

public class SqlImpersonatedCommand : DbCommand
{
    private readonly SqlCommand _command; //SqlImpersonatedCommand just calls into command
    public SqlImpersonatedCommand(string commandText)
    {
        _command = new SqlCommand(commandText);
    }
}

最新更新