2

我正在尝试使用 Nhibernate 在 SQL Server 中实现行级安全性。我想使用这种方法:https ://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-entity-framework-row-level-security/ 。

我在 nhibernate 中创建了一个拦截器:

public class TenantInterceptor : EmptyInterceptor
{
    private readonly ITenantResolver _tenantResolver;

    public TenantInterceptor(ITenantResolver tenantResolver)
    {
        _tenantResolver = tenantResolver;
    }

    public override void SetSession(ISession session)
    {
        string tenant = "sampleTenant";

        if (_tenantResolver.Current != null)
            tenant = _tenantResolver.Current.Id;

        string queryFormat = @"Exec sp_set_session_context @key=N'@Tenant', @value='{0}'";
        string query = string.Format(queryFormat, tenant);

        session.CreateSQLQuery(query)
            .ExecuteUpdate();

        base.SetSession(session);
    }
}

我以这种方式将它附加到会话中:

if (!CurrentSessionContext.HasBind(GetSessionFactory()))
{
    _session = GetSessionFactory().OpenSession(new TenantInterceptor(_tenantResolver));
    CurrentSessionContext.Bind(_session);
}
else
{
    _session = GetSessionFactory().OpenSession(new TenantInterceptor(_tenantResolver));
}

而且我在 SQL Server 中有以下代码:

CREATE SCHEMA [Security]
go

CREATE FUNCTION [Security].tenantAccessPredicate(@Tenant nvarchar(255))
RETURNS TABLE
WITH SCHEMABINDING
AS
    RETURN 
        SELECT 1 AS accessResult
        WHERE @Tenant = CAST(SESSION_CONTEXT(N'@Tenant') AS nvarchar(255)) OR @Tenant = ''

所以我认为我做的一切都是正确的。但是当我从我的应用程序运行查询时,我从来没有收到任何行。当我复制完全相同的 SQL 代码并从 SQL Server Management Studio 运行它时,一切正常,我得到了预期的行。

谁能帮我?我不知道我做错了什么。

4

1 回答 1

2

我知道这个问题已经很老了,但也许我的回答会对某人有所帮助。当我使用 ADO.NET 的 API 而不是 NHibernate 的 API 时,它对我有用:

public override void SetSession(ISession session)
{
    using (var cmd = session.Connection.CreateCommand())
    {
        var param1 = cmd.CreateParameter();
        param1.ParameterName = "@key";
        param1.Value = "TenantId";

        var param2 = cmd.CreateParameter();
        param2.ParameterName = "@value";
        param2.Value = _tenantResolver.Current.Id;

        cmd.CommandText = "sp_set_session_context";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.Add(param1);
        cmd.Parameters.Add(param2);

        cmd.ExecuteNonQuery();
    }

    base.SetSession(session);
}
于 2019-09-28T14:16:45.960 回答