Подключение к SQL серверу из плагинов
Предположим, у Вас есть потребность обратится к данным не CRM’ной базы данных SQL Server’а из плагина… Это может быть сделно, например, в целях интеграции с другой системой или обращение к общему хранилищу данных и т.д.
Проблема, с которой Вы столкнетесь, состоит в том, что системная учетная запись, из под которой плагин выполняется, не имеет доступ к SQL Server’у и базам данных. В Microsoft Dynamics CRM все плагины выполняются под системной учетной записью NT AUTHORITY\NETWORK SERVICE.
Поэтому у Вас есть два пути:
- Использовать интегрированную аутентификацию (т.е. c использованием доменной учетной записи)
- При этом SQL запрс будет выполнятся под учетной записью NT AUTHORITY\NETWORK SERVICE у которой, как уже говорилось нет необходимых прав (на подключение к Вашим базам данных). Поэтому Вы можете либо выдать ей необходимы права, либо заставить код выполнятся под конкретной учеткой (зарегистрированной в SQL сервере). Например, Вы может создать в SQL учетку основанную на учетной записи из Active Directory и соответствующую тому пользователю, который будет запускать плагин (если таких пользователей несколько, то и учеток в SQL Server’е необходимо создать несколько). Затем выдать права созданной учетки на выполнение необходимых действий (с Вашими базами данных). А чтобы выполнить SQL команды от лица конкретного SQL пользователя , Вы должны использоватьT-SQL конструкцию Execute AS при написании SQL запроса. Все это имеет смысл, например, если у Вас есть какие-нибудь хранимый процедуры на SQL сервере, которые необходимо запускать в контексте конкретных пользователей (точнее конкретный учетных записей в SQL сервере);
- Далее необходимо учетной записи NT AUTHORITY\NETWORK SERVICE (из под которой выполняется плагин) предоставить разрешения для подключения к SQL серверу;
- При интегрированной аутентификации строка подключения к SQL серверу в C#-коде будет выглядеть так:
Data Source=mySQLServer;Initial Catalog=myDataBaseName;Integrated Security=SSPI;
- Аутентификация SQL Server’а
- Для этого необходимо создать скульную учетку (через которую будете получать доступ к БД) и выдать ей необходимые права;
- Разрешить SQL серверу использовать собственную аутентификацию (если она у Вас не разрешена). Делается это в свойствах SQL сервера (щелчок правой кнопкой мыши по руту в Msnsgament Studio – properties — security). И не забудьте после этого рестартнуть SQL сервер;
- В этом случаи строка подключения к SQL серверу в C#-коде будет такой:
Data Source=mySQLServer;Initial Catalog=myDataBaseName;User Id=myUsername;Password=myPassword;Integrated Security=false;
Учтите, что т.к. придется хранить логин и пароль в чистом виде. То имеет смысл поместить его Secure Configuration, ну или захардкодит 🙂
Рассмотрим небольшой пример…
Создайте в SQL сервере учетную запись, сответствующую тому пользователю, из под которого будет выполнтся плагин. В данным примере, SQL запрос выполняется под доменной учеткой юзвера запустившего плагин, поэтому если система не найдет такой учетки, то свалится с ошибкой. При этом ничего не мешает Вам переписать код так, чтобы он выполнялся под одной конкретной учеткой (как виндовой, так и скульной) если у Вас нет необходимости выполнять SQL запрос в контексте конкретного юзвера;
- Т.к. я планирую использовать интегрированную аутентификацию, то сначала необходимо выдать различные права для учтеки NT AUTHORITY\NETWORK SERVICE из под которой выполняется плагин (права на олицетворение в частности). И т.к. это просто пример, то я выдам ей права сисадмина 🙂
- SQL запрос будет выполнятся под конкретным SQL-пользователем (учетная запись которого создана на основе учетки из Active Directory). Но, т.к. я работаю из под админа устанавливающего SQL сервер, то его учетка уже заведена 🙂 Но Вам необходимо ее создать (если она уже не создана) 🙂
- Создайте плагин и повесьте на него такой код:
using System; using System.Collections.Generic; using System.Text; using Microsoft.Crm.Sdk; using Microsoft.Crm.SdkTypeProxy; using Microsoft.Crm.Sdk.Query; using System.Data.SqlClient; public class AccessDatabase : IPlugin { string m_connectionString; // Передаем строку подключения (заданную во время регистрации плагина) к конструктору плагина. public AccessDatabase(string config, string secureConfig) { m_connectionString = config; } // При выполнении плагина... public void Execute(IPluginExecutionContext context) { // Шаг 1. Получаем доменное имя пользователя запустившего плагин ICrmService crmService = context.CreateCrmService(false); systemuser callingUser = (systemuser)crmService.Retrieve( EntityName.systemuser.ToString(), context.UserId, new ColumnSet(new string[] { "domainname" }) ); // Шаг 2. Подключаемся к SQL серверу используя строку подключения using (SqlConnection conn = new SqlConnection(m_connectionString)) { conn.Open(); SqlCommand comm = conn.CreateCommand(); // Шаг 3. Начинаем SQL олицетворение comm.CommandText = @"Execute as Login='" + callingUser.domainname + "'; "; // Шаг 4. Выполняем необходимые SQL команды comm.CommandText += "SELECT SUSER_NAME(); "; // Шаг 5. Возвращаем контекст обратно к Network Service comm.CommandText += "revert;"; comm.CommandType = System.Data.CommandType.Text; // Выводим в сообщении имя пользователя выполневшего SQL запрос (и которого мы выбрали с помощью оператора SELECT) throw new InvalidPluginExecutionException(comm.ExecuteScalar().ToString()); } } }
Данный код делает следующее:
- Получает строку подключения из Unsecure Configuration (ее мы зададим позже при регистрации плагина);
- Создает экземпляр CRM Service и отправляет ему запрос для извлечения доменной учетки юзвера, запустившего плагин;
- Используя строку подключения (из Unsecure Configuration) соединяемся с SQL сервером;
- Выполняем SQL команду под доменной учеткой, которую мы вытащили из записи пользователя, запустившего плагин;
- В данном примере, SQL запрос просто вернет доменную учтку пользователя из под которой этот SQL запрос выполнялся.
- Зарегистрируйте плагин на любое событии. При этом в Unsecure Configuration поместите строку такого вида:
Data Source=mySQLServer;Initial Catalog=myDataBaseName;Integrated Security=SSPI;
Только подставьте в нее Ваши имя SQL сервера и базы данных;
- Вызовите событие в CRM.
Я немного не понял. Мне нужно из плагина передать данные на другой сервер. В connectionString я указываю параметры, куда буду передавать. В Unsecure Configuration — здесь параметры, откуда буду передавать. Так. При срабатывании возникает ошибка login failed for user ‘СС\dynamics’.
Все спасибо разобрался сам.