我正在使用客户端服务器应用程序,我希望客户端使用用户的登录凭据向服务器进行身份验证,但我不希望用户键入用户名和密码。我当然不希望负责安全地处理密码。我只需要用户向我证明自己就是他们所说的那个人,然后我的服务器就可以继续进行并根据需要授予/拒绝命令。

我的用户是域的一部分,因此我希望能够使用他们在登录时创建的登录凭据。

我没有使用任何类型的Web服务,也不想使用。我同时控制客户端和服务器软件,并且两者均使用纯C#编写,并使用良好的ol'socket完成工作。

我宁愿使用纯C#/。Net来执行此操作,但是我愿意使用不安全的C#并在Win32 API上使用pinvokes,如果这意味着我可以完成工作。

我已经在Windows中阅读了一些有关SSPI的内容,但是由于这种应用程序开发对我来说是新的,所以我有点漆黑。

有人知道怎么做这个吗?是SSPI吗?如何在C#中使用SSPI?是否有.Net原生方式,以便我的代码可以保持可移植性?

最佳答案

更新:

SSPI是正确的方法。该API并不是很难使用,但是确实需要一个大小合适的项目才能包装到C#中。

在研究解决此问题所需的位的过程中,我编写了一个项目来在.Net中提供SSPI。下面,我描述了与Windows SSPI API接口(interface)的基础,以便任何人都可以复制我的结果。如果发现自己想在.Net中使用SSPI,建议您使用我创建的项目来解决此问题:

NSspi - A .Net interface to the SSPI API

SSPI为您提供包含身份验证 token 的原始字节数组,然后您可以决定如何传输-通过带有二进制格式的消息的套接字,自定义XML channel ,.Net Remoting,某种形式的WCF,heck甚至是串行端口来进行传输。您可以决定如何处理它们。使用SSPI,服务器可以对客户端进行身份验证,安全地标识客户端,甚至可以使用与客户端建立的安全上下文执行基本的消息处理过程,例如加密/签名。

SSPI API记录在这里:SSPI API overview

具体来看一下以下功能:

  • AcquireCredentialsHandle
  • 获取某种形式的凭据的句柄(例如,当前用户的登录名)。由服务器和客户端使用。
  • InitializeSecurityContext
  • 客户端用于与服务器建立安全上下文。
  • AcceptSecurityContext
  • 服务器使用它与客户端建立安全上下文。

  • 典型的工作流程是,双方将使用AcquireCredentialsHandle初始化其凭据。然后,身份验证周期开始并进行如下:
  • 客户端调用InitializeSecurityContext,不提供输入 token ,该 token 以字节数组的形式返回输出 token 。 ISC返回“ContinueNeeded”以指示认证周期未完成。
  • 客户端通过其希望的方式将 token 发送到服务器。
  • 服务器将接收到的 token 作为输入提供给AcceptSecurityContext,并生成自己的输出 token 。 ASC还返回“ContinueNeeded”以指示身份验证
    循环不完整。
  • 然后,服务器将其输出 token 发送到客户端。
  • 客户端将服务器 token 提供为InitializeSecurityContext的输入,InitializeSecurityContext返回新的输出 token 。
  • 客户端将其新的输出 token 发送到服务器。
  • ...

  • 此循环一直持续到客户端看到InitializeSecurityContext返回“确定”并且服务器看到AcceptSecurityContext返回“确定”为止。每个函数都可以返回“OK”,并且仍然提供输出 token (如非空返回所指示),以指示它仍然必须将数据发送到另一端。这样客户端就知道一半完成了,但是服务器仍然不完整。如果服务器在客户端之前完成,反之亦然。哪一方先完成(返回“OK”)取决于SSPI在幕后使用的特定安全软件包,任何SSPI使用者都应意识到这一点。

    上面的信息应该足以使任何人与SSPI系统接口(interface),以便在其应用程序中提供“Windows集成身份验证”并复制我的结果。

    在学习如何调用SSPI API时,下面是我的早期答案。

    我已经忘记了这个问题,几天前刚巧地回到了这个问题。我确实需要在一两年内解决这个问题:)

    .NET中可能有此功能,而我目前正在开发我打算发布的.Net SSPI包装器。

    我的工作基于我发现的Microsoft的SSPI samples

    该示例包含一个C++/CLI托管程序集,该程序集实现SSPI API的必要部分(位于从REMSSPI.exe文件提取的Microsoft\Samples\Security\SSPI\SSPI文件夹中)。然后,它们有两个UI,一个客户端应用程序和一个服务器应用程序,均使用C#编写,它们使用此API来执行SSPI身份验证。

    这些UI使用.Net远程处理功能将它们绑定(bind)在一起,但是如果我正确理解SSPI API,客户端和服务器需要交换的唯一信息就是包含安全上下文 token 数据的byte []。轻松集成到您想要的任何通信基础架构中;就我而言,是我自己设计的二进制协议(protocol)。

    关于使示例工作的一些注意事项-它们具有“SSPI”库源代码,尽管我已使其在2008年下运行,但该源代码最好在VS 2005下编译。 2010年或更高版本需要进行一些重新设计,因为它们使用的语言结构已被弃用。您可能还需要修改属于平台SDK的头文件,因为它们使用了指向unconst变量的const指针分配,而且我不知道让编译器满意的更好方法(我从未使用过C++/CLI之前)。

    它们确实在Microsoft\Samples\Security\SSPI\bin文件夹中包含已编译的SSPI dll。要使客户端/服务器二进制文件正常工作,您必须将该dll复制到其bin目录中,否则将失败。

    总结一下:
  • 转到here以下载REMSSPI.exe示例自解压zip。
  • 提取REMSSPI.exe文件(两次..)
  • Microsoft\Samples\Security\SSPI\
  • bin\-包含已编译的dll Microsoft.Samples.Security.SSPI.dll
  • SSPI\-包含dll
  • 的源代码
  • Sample\-包含UI源代码
  • bin\-包含构建UI示例。将SSPI.dll文件复制到此处,然后运行ControlPanel.Client.exeControlPanel.Server.exe
  • 08-07 17:12