Создать логин через SqlCommand - параметры не подставляются - PullRequest
0 голосов
/ 02 октября 2019

Я пытаюсь создать новую учетную запись SQL на C #. Я пытался установить следующие параметры запроса:

using (SqlConnection connection = new SqlConnection(sqlServerConnString))
{
    connection.Open();

    string addLogin = "CREATE LOGIN [@databaseUserId] WITH PASSWORD = '@databasePassword';";
    using (SqlCommand command = new SqlCommand(addLogin, connection))
    {
        // Attempt 1.
        command.Parameters.AddWithValue("@databaseUserId", databaseUserId);
        command.Parameters.AddWithValue("@databasePassword", databasePassword);

        // Attempt 2.
        command.Parameters.Add(new SqlParameter("@databaseUserId", databaseUserId));
        command.Parameters.Add(new SqlParameter("@databasePassword", databasePassword));

        // Attempt 3.
        command.Parameters.Add("databaseUserId", System.Data.SqlDbType.NVarChar).Value = databaseUserId;
        command.Parameters.Add("databasePassword", System.Data.SqlDbType.NVarChar).Value = databasePassword;

        command.ExecuteNonQuery();
    }
}

Каждая «попытка» запускалась индивидуально.

Независимо от того, какую версию я пробую, команда завершается без ошибок. Однако когда я проверяю имена входа на SQL Server, я вижу, что он создал пользователя с именем "@databaseUserId".

Я могу подтвердить, что переменные databaseUserId и databasePassword не равны нулю.

Чего мне не хватает?

1 Ответ

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

Я не разработчик C #, поэтому доверяю , что ваш код верен.

Как я заявляю в своем комментарии "Вы не можетеиспользуйте переменную для замены строкового литерала. Приведенное выше попытается создать логин с именем @databaseUserId , а не со значением @databaseUserId. " Также будет установлен пароль этого логинабыть строкой '@databasePassword' (опять же, не значением @databasePassword).

Вам потребуется использовать динамический SQL для достижения этого в вашем утверждении. Я верю , что это сработает, но у меня нет возможности проверить.

using (SqlConnection connection = new SqlConnection(sqlServerConnString))
{
    connection.Open();

    //string addLogin = "CREATE LOGIN [@databaseUserId] WITH PASSWORD = '@databasePassword';";
    string addLogin = "DECLARE @SQL nvarchar(MAX) = N'CREATE LOGIN ' + QUOTENAME(@databaseUserId) + N' WITH PASSWORD = N' + QUOTENAME(@databasePassword,'''') + N';'; EXEC sp_executesql @SQL;";
    using (SqlCommand command = new SqlCommand(addLogin, connection))
    {

        command.Parameters.Add("databaseUserId", System.Data.SqlDbType.NVarChar,128).Value = databaseUserId;
        command.Parameters.Add("databasePassword", System.Data.SqlDbType.NVarChar,128).Value = databasePassword;

        command.ExecuteNonQuery();
    }
}

Обратите внимание на важное использование QUOTENAME здесь, и что вы используете SQLвызов все еще параметризован на стороне приложения вещей. Поскольку вам нужно использовать буквенные строки для значений, вы должны ввести их (что обычно считается ). QUOTENAME правильно цитирует ваши строки, что означает, что воздействие инъекций значительно уменьшено (некоторые из тех, кто просто делает это теперь, будут инъекционными "иммунными").

Итак, если кто-то попыталсявведите имя для входа, тогда символы будут экранированы. Например, значение N'L] WITH PASSWORD = 'abc123!"£'; ALTER SERVER ROLE sysadmin ADD MEMBER L;--' будет заключено в кавычку к значению [L]] WITH PASSWORD = 'abc123!"£'; ALTER SERVER ROLE sysadmin ADD MEMBER L;--], и логин с таким (глупым) именем будет фактически создан (при условии, что указан пароль значения). Для пароля, поскольку он должен быть строковым литералом, а не литералом, я использую 2-й параметр, чтобы указать SQL Server, с каким символом заключать строку в кавычки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...