Реализовать уровень безопасности в NHibernate в SQL Server 2016

Я пытаюсь реализовать безопасность на уровне строк в SQL Server, используя Nhibernate. Я хотел использовать этот подход: 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, все работает, и я получаю ожидаемые строки.

Может кто-нибудь мне помочь? Я понятия не имею, что я сделал неправильно.


person Marek    schedule 26.09.2016    source источник


Ответы (1)


Я знаю, что этот вопрос довольно старый, но, возможно, мой ответ поможет кому-то. У меня это сработало, когда я использовал API ADO.NET вместо NHibernate:

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);
}
person starkpl    schedule 28.09.2019