System.Security.SecurityException с функцией CLR - PullRequest
2 голосов
/ 31 октября 2019

Во-первых, я скажу, что эта проблема связана с моим предыдущим постом .

Однако я перейду сюда для справки.

ПроблемаЯ получаю сообщение об ошибке:

Сообщение 6522, уровень 16, состояние 1, процедура PerfInsert, строка 0 [Строка пакетного запуска 31]. Ошибка .NET Framework во время выполнения пользователяопределенная подпрограмма или агрегат "PerfInsert": System.Security.SecurityException: Запрос не выполнен. System.Security.SecurityException: в MiddleMan.MiddleMan.CreateCommand (SqlString tblString, SqlString featureName, SqlString connectionString, SqlString perfionConnectionString, SqlString logFile).

необходимо 1011 *

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

1 Ответ

2 голосов
/ 31 октября 2019

Вы используете многопоточность, так что да, сборка 100% должна иметь PERMISSION_SET = UNSAFE.

Кроме того, поскольку у вас уже есть настроенный асимметричный ключ и связанный логин (спасибо за это и не с использованием TRUSTWORTHY ON), перед установкой сборки в UNSAFE необходимо сделать следующее:

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

, а затем:

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

или, если вы создаете логин на основе асимметричного ключа и сначала предоставляете ему разрешение UNSAFE ASSEMBLY, тогда вы можете просто использовать UNSAFE вместо SAFE в операторе CREATE ASSEMBLY.

Начиная с SQL Server 2017, вам нужно будет создать асимметричный ключ и связанный логин до создания сборки. Асимметричный ключ и логин входят в [master], в то время как сборка может идти в любую БД (включая [master], но обычно лучше не помещать туда собственный код).

Если вы уже используете SQL Server 2017или новее, и если код, показанный в вопросе, находится в фактическом порядке, в котором вы его выполняете, то я бы предположил, что вы уже установили базу данных на TRUSTWORTHY ON или отключили «CLR строгая безопасность». В противном случае вы вообще не смогли бы создать сборку без предварительного создания имени входа на основе сигнатуры , а предоставило разрешение UNSAFE ASSEMBLY. Если я прав в этом, вы можете снова включить «CLR строгую безопасность» и / или включить TRUSTWORTHY OFF для этой базы данных.

Кроме того, как я отметил по вашему связанному вопросу (тот, который связан с этимвопрос), вы должны использовать SqlString вместо SqlChars. SqlString.Value возвращает .NET string, а SqlChars.Value возвращает char[]. Давным-давно люди связывали SqlChars с NVARCHAR(MAX) и SqlString с NVARCHAR(1-4000), но это было связано только с тем, что Visual Studio / SSDT использовал эти сопоставления в качестве значений по умолчанию при создании DDL для публикации проекта базы данных. Но между ними никогда не было никакого технического / строкового отображения. Вы можете использовать любой тип .NET с любым типом данных T-SQL.

Также, пожалуйста, соблюдайте осторожность (и много проверяйте) при использовании многопоточности из SQLCLR.

Пожалуйста, посетите SQLCLR Info для получения дополнительных ресурсов, связанных с работой с SQLCLR в целом.

Похожие сообщения:

  1. System.Web в SQL ServerФункция CLR (на DBA.StackExchange)
  2. CREATE PROCEDURE получает «Msg 6567, уровень 16, состояние 2» для хранимой процедуры SQLCLR
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...