Поделиться через


Разработка SSPI клиента с аутентификацией

Для всех сеансов клиента или сервера RPC требуется привязка между клиентом и сервером. Чтобы добавить безопасность для клиентских и серверных приложений, программы должны использовать проверку подлинности привязки. В этом разделе описывается процесс создания аутентификации привязки между клиентом и сервером.

Дополнительные сведения см. в разделе Процедуры, используемые с большинством пакетов безопасности и протоколов в пакете SDK для платформы.

Создание дескрипторов привязки на стороне клиента

Чтобы создать аутентифицированный сеанс с серверной программой, клиентские приложения должны предоставить аутентификационные данные с помощью дескриптора привязки. Чтобы настроить дескриптор привязки с проверкой подлинности, клиенты вызывают функцию RpcBindingSetAuthInfo или RpcBindingSetAuthInfoEx. Эти две функции почти идентичны. Единственное различие между ними заключается в том, что клиент может указать качество обслуживания с помощью функции RpcBindingSetAuthInfoEx.

В следующем фрагменте кода показано, как может выглядеть вызов к RpcBindingSetAuthInfo.

// This code fragment assumes that rpcBinding is a valid binding 
// handle between the client and the server. It also assumes that
// pAuthCredentials is a valid pointer to a data structure which
// contains the user's authentication credentials.

dwStatus = DsMakeSpn(
    "ldap",
    "ServerName.domain.com",
    NULL,
    0,
    NULL,
    &pcSpnLength,
    pszSpn);

//...

rpcStatus = RpcBindingSetAuthInfo(
    rpcBinding,                       // Valid binding handle
    pszSpn,                           // Principal name 
    RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,  // Authentication level
    RPC_C_AUTHN_GSS_NEGOTIATE,        // Use Negotiate SSP
    NULL,                             // Authentication credentials <entity type="ndash"/> use current thread credentials
    RPC_C_AUTHZ_NAME);                // Authorization service

После того как клиент успешно вызывает функции RpcBindingSetAuthInfo или RpcBindingSetAuthInfoEx, библиотека времени выполнения RPC автоматически проверяет подлинность всех вызовов RPC в привязке. Уровень безопасности и проверки подлинности, которые выбирает клиент, применяется только к этому дескриптору привязки. Дескриптор контекста, производный от дескриптора привязки, будет использовать ту же информацию безопасности, но последующие изменения дескриптора привязки не будут отражены в дескрипторах контекста. Дополнительные сведения см. в разделе Контекстные дескрипторы.

Уровень проверки подлинности действует до тех пор, пока клиент не выберет другой уровень или пока процесс не завершится. Большинству приложений не потребуется изменить уровень безопасности. Клиент может запросить любой дескриптор привязки, чтобы получить сведения об авторизации, вызвав RpcBindingInqAuthClient и передав этот дескриптор привязки.

Предоставление учетных данных клиента серверу

Серверы используют сведения о привязке клиента для обеспечения безопасности. Клиенты всегда передают дескриптор привязки в качестве первого параметра вызова удаленной процедуры. Однако серверы не могут использовать дескриптор, если он не объявлен в качестве первого параметра для удаленных процедур в файле IDL или в файле конфигурации приложения сервера (ACF). Вы можете перечислить дескриптор привязки в файле IDL, но это заставляет всех клиентов объявлять и управлять дескриптором привязки, а не использовать автоматическую или неявную привязку. Дополнительные сведения см. в IDL и ACF-файлах.

Другой метод — не упоминать дескрипторы привязки в файле IDL и поместить атрибут explicit_handle в ACF сервера. Таким образом, клиент может использовать тип привязки, подходящий для приложения, в то время как сервер использует дескриптор привязки, как если бы он был объявлен явным образом.

Процесс извлечения учетных данных клиента из дескриптора привязки выполняется следующим образом:

  • Клиенты RPC вызывают RpcBindingSetAuthInfo и включают аутентификационную информацию в информацию о привязке, передаваемую серверу.
  • Как правило, сервер вызывает RpcImpersonateClient, чтобы вести себя так, как будто это был клиент. Если дескриптор привязки не прошел проверку подлинности, вызов завершается сбоем с RPC_S_NO_CONTEXT_AVAILABLE. Чтобы получить имя пользователя клиента, вызовите RpcBindingInqAuthClient во время олицетворения или в Windows XP или более поздних версиях Windows, вызовите RpcGetAuthorizationContextForClient, чтобы получить контекст авторизации, а затем используйте функции Authz для получения имени.
  • Сервер обычно вызывает CreatePrivateObjectSecurity для создания объектов с помощью списков управления доступом. После этого последующие проверки безопасности становятся автоматическими.