【问题标题】:Using NHibernate with SQL Server Application Roles将 NHibernate 与 SQL Server 应用程序角色一起使用
【发布时间】:2011-12-14 14:53:30
【问题描述】:

我正在使用 NHibernate (Fluently) 与一个数据库进行交互,该数据库被锁定为除应用程序角色之外的所有角色。

我可以直接使用存储过程:sp_setapprolesp_unsetapprole 在 SQL Server Management Studio 中使用应用程序角色,但尝试执行此操作时遇到问题使用 NHibernate:

using (var session = SessionFactory.OpenSession())
{
    byte[] cookie;

    // 1) Set the application role
    using (var command = session.Connection.CreateCommand())
    {
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "sp_setapprole";
        command.Parameters.Add(new SqlParameter("@rolename", RoleName));
        command.Parameters.Add(new SqlParameter("@password", RolePassword));
        command.Parameters.Add(new SqlParameter("@fCreateCookie", true));
        command.Parameters.Add(
            new SqlParameter
                {
                    ParameterName = "@cookie",
                    DbType = DbType.Binary,
                    Direction = ParameterDirection.Output,
                    Size = 8000
                });

        // This works perfectly fine
        command.ExecuteNonQuery();
        var outVal = (SqlParameter)command.Parameters["@cookie"];

        // This returns a byte array value for the cookie generated
        cookie = (byte[])outVal.Value;
    }

    // 2) This line dutifully retreives my contrived Person object but renders
    //    part 3) of this saga next to useless because it performs a logout
    //    (identified with SQL Profiler) and the app role/cookie is forgotten.
    session.CreateCriteria(typeof(Person)).List<Person>().FirstOrDefault();

    // 3) Unset the application role
    using (var command = session.Connection.CreateCommand())
    {
        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = "sp_unsetapprole";
        command.Parameters.Add(new SqlParameter("@cookie", cookie));
        command.ExecuteNonQuery();
    }
}

总而言之,在上述示例中执行 1) 和 3) 之间的任何操作都会导致应用程序崩溃。有两种不同的方式,取决于我是否在池中:

Pooling - 当前命令出现严重错误。结果(如果有)应丢弃。

未池化 - 无法取消设置应用程序角色,因为未设置或 cookie 无效。

我不确定这是否有帮助,但我正在连接以下内容(通常会稍有不同,但我需要配置 Pooling 属性):

private static ISessionFactory CreateSessionFactory()
{
    return Fluently.Configure().Database(
        MsSqlConfiguration.MsSql2008.ConnectionString(
            "Data Source=(local);" +
            "Initial Catalog=PeopleDB;" +
            "Integrated Security=False;" +
            "User ID=someuserid;" +
            "Password=somepassword" +
            "Pooling=False"))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>())
        .BuildSessionFactory();
}

仅供参考,在上述代码中连接的用户对数据库绝对没有权限,这至少证明 sp_setapprole 是有效的。

有没有人遇到过这个并设法解决它?我有一个很好的谷歌,但什么也没找到。

提前致谢, 抢

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate fluent


    【解决方案1】:

    NH 在需要时使用IConnectionProvider 创建和关闭连接。如果应用程序中使用的每个连接都使用相同的身份验证过程,最好实现自己的IConnectionProvider 并使用MsSqlConfiguration.MsSql2008.Provider&lt;YourOwnConnectionProvider&gt;() 进行配置;

    class MyConnectionProvider : DriverConnectionProvider
    {
        public override IDbConnection GetConnection()
        {
            var connection = base.GetConnection();
    
            byte[] cooky;
            // TODO: authenticate
    
            return new MyConnectionWrapper(connection, cooky);
        }
    
        public override void CloseConnection(IDbConnection conn)
        {
            var myConn = conn as MyConnectionWrapper;
            if (myConn != null)
            {
                // TODO: deregister with myConn.Cooky;
            }
            base.CloseConnection(conn);
        }
    }
    

    【讨论】:

    • 感谢您的回答 Firo。我很好奇 MyConnectionWrapper 实现了什么......你能解释一下那个类的目的吗?
    • 它只是一个装饰器,它将所有内容委托给底层连接,并将 cookie 作为属性保存以在关闭时取消注册
    • 它正在工作!非常感谢您的帮助 Firo,最后我要做的就是在 GetConnection 覆盖中调用 setapprole,在 CloseConnection 覆盖中调用 unsetapprole!
    • 就是这个想法。如果它解决了您的问题,您介意接受答案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    相关资源
    最近更新 更多