SQL Server 使用CLR函数时出现系统安全性异常

3lxsmp7m  于 2022-12-22  发布在  其他
关注(0)|答案(1)|浏览(180)

首先,我要说这个问题与my previous post有关。
不过,我会把所有东西都移到这里以供参考。
我遇到的问题是我仍然收到错误:
Msg 6522,级别16,状态1,过程PerfInsert,第0行[批处理开始第31行]在执行用户定义的例程或聚合“PerfInsert”期间出现.NET Framework错误:System.Security.SecurityException:请求失败。系统。安全。安全异常:创建命令(SqlString表字符串、SqlString功能名称、SqlString连接字符串、SqlString性能连接字符串、SqlString日志文件)。
尽管我相信我已经按照所有必要的步骤正确设置了这个。我甚至已经验证了SQL Server是否有权限访问文件的目录。
有谁知道我还能查什么来看看缺了什么吗?
或者我是否需要将此程序集设置为“不安全”程序集?
C#代码:

using Microsoft.SqlServer.Server;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;

    namespace MiddleMan
{
    public static class MiddleMan
    {
        [SqlProcedure(Name = "PerfInsert")]
        public static SqlInt32 CreateCommand(SqlString tblString, SqlString featureName, SqlString connectionString, SqlString perfionConnectionString, SqlString logFile)
        {
            Process compiler = new Process();
            compiler.StartInfo.FileName = "C:\\SQL Server C# Functions\\PerfionLoader\\PerfionLoader\\bin\\Release\\PerfionLoader.exe";
            compiler.StartInfo.Arguments = tblString.Value + " " + featureName.Value + " " + connectionString.Value + " " + perfionConnectionString.Value + " " + logFile.Value;
            //compiler.StartInfo.UseShellExecute = false;
            //compiler.StartInfo.RedirectStandardOutput = true;
            compiler.Start();
            return SqlInt32.Zero;
        }
    }
}

SQL代码:

CREATE ASSEMBLY PerfInsert
    AUTHORIZATION dbo
    FROM '\\bk-int-1\c$\SQL Server C# Functions\MiddleMan\MiddleMan\bin\Release\MiddleMan.dll'
    WITH PERMISSION_SET = SAFE
GO

CREATE ASYMMETRIC KEY [Brock.Retail_Brock.Retail_Brock]
  AUTHORIZATION [dbo]
  FROM EXECUTABLE FILE = '\\bk-int-1\c$\SQL Server C# Functions\MiddleMan\MiddleMan\bin\Release\MiddleMan.dll';

  CREATE LOGIN BrokcRetail
    FROM ASYMMETRIC KEY [Brock.Retail_Brock.Retail_Brock]

CREATE PROCEDURE PerfInsert
    (
        @tblString nvarchar(max)
        , @featureName nvarchar(max)
        , @connectionString nvarchar(max)
        , @perfionConnectionString nvarchar(max)
        , @logFiel nvarchar(max)
    )
    AS EXTERNAL NAME PerfInsert.[MiddleMan.MiddleMan].[CreateCommand]
GO
xzv2uavs

xzv2uavs1#

您使用的是多线程,所以是的,程序集100%需要具有PERMISSION_SET = UNSAFE
此外,由于您已经设置了非对称密钥和关联的登录(感谢您这样做,并且 * 不 * 使用TRUSTWORTHY ON),因此在将Assembly设置为UNSAFE之前,您需要执行以下操作:

USE [master];
GRANT UNSAFE ASSEMBLY TO [BrokcRetail];

然后:

USE [{db_containing_assembly_hopefully_not_master];
ALTER ASSEMBLY [PerfInsert] WITH PERMISSION_SET = UNSAFE;

或者,如果您创建基于非对称密钥的登录并首先授予其UNSAFE ASSEMBLY权限,则只需在CREATE ASSEMBLY语句中使用UNSAFE而不是SAFE
从SQL Server 2017开始,您需要在 * 创建程序集之前 * 创建非对称密钥和关联的登录名。非对称密钥和登录名进入[master],而程序集可以进入任何DB(包括[master],但通常最好不要在其中放置自定义代码)。
如果您已经在使用SQL Server 2017或更高版本,并且问题中显示的代码符合您执行代码的实际顺序,那么我猜您已经将数据库设置为TRUSTWORTHY ON或禁用了"CLR严格安全"。否则,如果不首先创建基于签名的登录,您根本无法创建程序集 * 和 *授予了UNSAFE ASSEMBLY权限。如果我对这一点是正确的,您可以重新启用"CLR严格安全"和/或为该数据库打开TRUSTWORTHY OFF
另外,正如我在你的相关问题中提到的(在这个问题中链接到的那个),您应该使用SqlString而不是SqlCharsSqlString.Value返回一个. NET string,而SqlChars.Value返回一个char[]。很久以前,人们将SqlCharsNVARCHAR(MAX)相关联,将SqlStringNVARCHAR(1-4000)相关联,但这只是因为Visual Studio/SSDT在生成DDL以发布数据库项目时使用这些Map作为默认值。但它们之间从来没有任何技术/字符串Map。您可以将任何. NET类型与任何T-SQL数据类型一起使用。
另外,在SQLCLR中使用多线程时请谨慎(并进行大量测试)。
请访问SQLCLR Info以获取更多与使用SQLCLR有关的资源。

    • 相关帖子:**
  1. System.Web in SQL Server CLR Function(在数据库管理员.堆栈交换上)
  2. CREATE PROCEDURE gets “Msg 6567, Level 16, State 2” for SQLCLR stored procedure

相关问题