Ошибка входа в собственный клиент MS SQL для пользователя при подключении через PHP

У меня есть сервер Windows 2008 R2 Datacenter с IIS 7.5, MS SQL 2012 Express, использующий PHP 5.6, который пытается подключиться к созданной мной базе данных testDB через проверку подлинности Windows, но мне это не удается.

Вот мой PHP, который я использую для подключения к моему SQL Server\Instance:

<?php

$serverName = "nmc-intranet\intranetsql";
$connectionInfo = array("Database"=>"testDB", "UID"=>"username", "PWD"=>"password");
$conn = sqlsrv_connect( $serverName, $connectionInfo);

if ( $conn ) {
echo "Connection successful.<br />";
} else {
    echo "Connection failed.<br />";
    die( print_r( sqlsrv_errors(), true));
}

?>

Когда я запускаю это, я получаю:

Ошибка подключения. Массив ( [0] => Массив ( [0] => 28000 [SQLSTATE] => 28000 1 => 18456 [код] => 18456 2 => [Microsoft][SQL Server Native Client 11.0][SQL Server]Ошибка входа для пользователя 'jaj'. [message] => [Microsoft][SQL Server Native Client 11.0 [SQL Server] Ошибка входа для пользователя «jaj». a-website-in-iis/" rel="nofollow noreferrer">1 => Array ( [0] => 28000 [SQLSTATE] => 28000 1 => 18456 [код] = > 18456 2 => [Microsoft][SQL Server Native Client 11.0][SQL Server]Ошибка входа пользователя ' jaj' [сообщение ] => [Microsoft][SQL Server Native Client 11.0][SQL Server]Ошибка входа для пользователя 'jaj'. ))

В MS SQL я добавил имя пользователя в «Безопасность»> «Логины» и сопоставил testDB и дал схему dbo. Пользователь также имеет роль сервера sysadmin. Я могу подключиться к testDB через CLI SQLCMD /S nmc-intranet\intranetSQL /E /d testDB под именем пользователя. Я также могу подключиться к серверу\экземпляру через удаленный сеанс SSMS, поэтому я считаю, что свойства удаленного подключения верны. Я проверил шаги, упомянутые в ответе, найденном здесь.

Для IIS я пытался установить соединение разными способами, но и здесь безуспешно. Итак, я предполагал, что моя проблема заключается в ошибке входа в систему SQL. Я менял строку подключения с помощью диспетчера IIS в узле NMC-Intranet, а также в узле веб-сайта по умолчанию, и там у меня не получилось. Моя текущая строка подключения в web.config — это то, что было там по умолчанию после внесения изменений в IIS Manger, и выглядит следующим образом:

<connectionStrings>
    <remove name="LocalSqlServer" />
    <add connectionString="Server=nmc-intranet;Database=testDB;Integrated Security=true" name="LocalSqlServer" providerName="System.Data.SqlClient" />
</connectionStrings>

Я попытался изменить его на следующее, что нашел здесь, и до сих пор не имели успеха.

<connectionStrings>
    <add connectionString="Server=.\SQLEXPRESS;Database=testDB;User ID=username;Password=password" name="LocalSqlServer" providerName="System.Data.SqlClient" />
</connectionStrings>

В IIS DefaultAppPool я также попытался изменить идентификатор модели процесса на имя пользователя/пароль. Я читал об аутентификации Kerberos здесь, но при доступе к интрасети с включенной функцией он запрашивает у пользователей имя пользователя/пароль даже для просмотра домашней страницы.

Надеюсь, я правильно задал этот вопрос, как нашел здесь, поскольку предыдущие вопросы не были хорошо приняты. Я провел много исследований, но я не знаю, что я мог упустить, и я сделал так много изменений и отменил их, поскольку они не работали, я просто надеюсь на какое-то направление того, что мне может понадобиться попробовать дальше. Я, скорее всего, что-то неправильно истолковал, так как не имею полного представления о том, как нужно устанавливать соединение, и пропустил шаг или упустил какую-то информацию.

Я здесь не профессионал, просто пытаюсь собрать все это вместе из Интернета, заставить его работать и, надеюсь, чему-то научиться.

Конец игры Я хочу, чтобы пользователи входили в интрасеть через AD и загружали файлы, создавали свои собственные сообщения, создавали своего рода каталог, которым можно было бы управлять через интрасеть, возможно, имели IM (?) и действительно просто обучение опыт.

Спасибо.


person Leavii    schedule 28.11.2018    source источник
comment
Вы должны проверить журнал ошибок SQL Server для этого входа в систему. Следующая строка объяснит вам причину сбоя   -  person sepupic    schedule 29.11.2018
comment
@sepupic Спасибо за предложение, в следующий раз я обязательно сначала проверю журнал!   -  person Leavii    schedule 29.11.2018


Ответы (1)


Решение:

Если вы хотите подключиться к SQL Server с использованием проверки подлинности Windows, удалите параметры подключения UID и PWD. Когда вы используете эти параметры, драйвер PHP пытается подключиться с использованием аутентификации SQL Server (я предполагаю, что jaj является значением для UID).

<?php
$serverName = "nmc-intranet\intranetsql";
$connectionInfo = array(
    "Database"=>"testDB"
);
$conn = sqlsrv_connect($serverName, $connectionInfo);

if ($conn === false) {
    echo "Connection failed.<br />";
    die( print_r( sqlsrv_errors(), true));
} else {
    echo "Connection successful.<br />";
}
?>

Пояснения:

Драйверы Microsoft для PHP для SQL Server могут подключаться к SQL Server с помощью Проверка подлинности Windows или с помощью Аутентификация SQL Server. При использовании проверки подлинности Windows для подключения к серверу используется идентификатор процесса или потока веб-сервера (если веб-сервер использует олицетворение), а не идентификатор конечного пользователя. Я использую этот скрипт для получения дополнительной информации:

<?php
# ---------------------------------------
# SQL Server authentication
# ---------------------------------------
echo "SQL Server authentication"."</br>";
$server = 'server\instance,port';
$cinfo = array(
    "Database"=>'master',
    "UID"=>'login',
    "PWD"=>'password'
);
$conn = sqlsrv_connect($server, $cinfo);
if( $conn === false )
{
    echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
    exit;
}
$sql = 
    "SELECT 'SUSER_SNAME' AS [NAME], CONVERT(nvarchar(128), SUSER_SNAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'SUSER_NAME' AS [NAME], CONVERT(nvarchar(128), SUSER_NAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'USER_NAME' AS [NAME], CONVERT(nvarchar(128), USER_NAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'USER_ID' AS [NAME], CONVERT(nvarchar(128), USER_ID()) AS [VALUE]";
$stmt = sqlsrv_query($conn, $sql);
if( $stmt === false ) {
    echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
    exit;
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
    echo $row['NAME'].": ".$row['VALUE']."</br>";
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);


# ---------------------------------------
# Windows authentication
# ---------------------------------------
echo "Windows authentication"."</br>";
$server = 'server\instance,port';
$cinfo = array(
    "Database"=>'master'
);
$conn = sqlsrv_connect($server, $cinfo);
if( $conn === false )
{
    echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
    exit;
}
$sql = 
    "SELECT 'SUSER_SNAME' AS [NAME], CONVERT(nvarchar(128), SUSER_SNAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'SUSER_NAME' AS [NAME], CONVERT(nvarchar(128), SUSER_NAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'USER_NAME' AS [NAME], CONVERT(nvarchar(128), USER_NAME()) AS [VALUE]".
    "UNION ALL ".
    "SELECT 'USER_ID' AS [NAME], CONVERT(nvarchar(128), USER_ID()) AS [VALUE]";
$stmt = sqlsrv_query($conn, $sql);
if( $stmt === false ) {
    echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
    exit;
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
    echo $row['NAME'].": ".$row['VALUE']."</br>";
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
?>
person Zhorov    schedule 29.11.2018
comment
Спасибо за это, теперь я получаю успешное соединение. Я добавил нижнюю часть кода, который вы предоставили, и он соединяется с USER_NAME: NT AUTHORITY\NETWORK SERVICE. Я не знаю, полностью ли я пропустил UID/PWD для аутентификации SQL или неправильно понял. Я предположил, что если я разрешаю jaj к SQL-серверу, соединение должно использовать то же самое. Теперь мне интересно, как ограничить доступ пользователей к базе данных SQL с помощью проверки подлинности Windows? Я читал, что это более безопасно, или, может быть, я неправильно понял. В любом случае, надеюсь, что в будущем я буду читать более внимательно. - person Leavii; 29.11.2018
comment
@Leavii Вы должны установить соответствующий режим аутентификации IIS. Если вы видите NT AUTHORITY\NETWORK SERVICE в качестве имени пользователя, я предполагаю, что оно анонимно. - person Zhorov; 29.11.2018
comment
Это определенно то, что мне нужно больше исследовать. Я читал о том, как подключить IIS к MS SQL, но у меня возникли проблемы с поиском этого источника. В учебнике указано, что необходимо установить идентификатор модели процесса DefaultAppPool из ApplicationPoolIdentity в NetworkService. Затем разрешите NetworkService доступ к MS SQL. До сих пор я нашел это, stackoverflow.com/questions/37575752/, и, надеюсь, это поможет мне двигаться в правильном направлении. - person Leavii; 03.12.2018
comment
Удален NetworkService, и теперь я получаю Cannot open database "testDB" requested by the login. The login failed, так что у меня есть еще кое-какая работа. По этой ссылке выше я читал о Kerberos, но мне нужно перечитать, так как я не видел, где есть возможность не требовать от пользователей входа в интрасеть даже на домашней странице. - person Leavii; 03.12.2018