编写经过身份验证的 SSPI 服务器
在客户端和服务器程序之间进行经过身份验证的通信之前,服务器必须注册其身份验证信息。 具体而言,服务器必须注册其主体名称并指定它使用的身份验证服务。 有关主体名称的详细信息,请参阅 主体名称。 有关身份验证服务的详细信息,请参阅 身份验证服务。
为了注册其身份验证信息,服务器调用 RpcServerRegisterAuthInfo 函数。 将指向主体名称的指针作为第一个参数的值传递。 将第二个参数设置为一个常量,该常量指示应用程序将使用的身份验证服务。 有关身份验证服务的说明,请参阅 Authentication-Service 常量。
服务器还可以将密钥获取函数的地址作为第三个参数的值传递。 请参阅 密钥获取函数。 若要对所选身份验证服务使用默认密钥获取函数,请将第三个参数设置为 NULL。 RpcServerRegisterAuthInfo 函数的最后一个参数是传递给密钥获取函数的指针数据(如果提供密钥获取函数)。 以下代码片段中显示了对 RpcServerRegisterAuthInfo 的调用。
dwStatus = DsMakeSpn(
"ldap",
"ServerName.domain.com",
NULL,
0,
NULL,
&pcSpnLength,
pszSpn);
rpcStatus = RpcServerRegisterAuthInfo (
psz, // Server principal name
RPC_C_AUTHN_GSS_NEGOTIATE, // Authentication service
NULL, // Use default key function
NULL); // No arg for key function
此外,服务器还可以为 RPC 运行时库提供授权函数。 若要设置授权函数,请调用 RpcMgmtSetAuthorizationFn 函数。
分布式应用程序的服务器部分可以调用函数 RpcBindingInqAuthClient 或 RpcBindingInqAuthClientEx 来查询绑定句柄以获取身份验证信息。
如果服务器注册到安全支持提供程序,则不会调度凭据无效的客户端调用。 但是,将调度没有凭据的调用。 有三种方法可以阻止这种情况发生:
- 使用 RpcServerRegisterIfEx 注册接口,并具有安全回调函数;这将导致 RPC 运行时库自动拒绝对该接口的未经身份验证的调用。 注册回调函数与检查访问凭据的其他方法兼容;回调函数本身可以调用 RpcImpersonateClient、 RpcGetAuthorizationContextForClient 或 RpcBindingInqAuthClientEx 函数或其他函数。 但是,这些函数不能使用传递给函数的参数,因为它们在此时不会被取消封送。
重要
使用 RpcServerRegisterIfEx 注册具有安全回调函数的接口是检查客户端凭据的最常用方法。
- 调用 RpcBindingInqAuthClient 以确定客户端正在使用的安全级别。 然后,如果客户端未经身份验证,存根可能会返回错误。