更新:
对于这个问题,SSPI是正确的方法。该API不太难使用,但需要一个相当大的项目来包装成C#。
在研究解决这个问题所需的必要部分的过程中,我编写了一个项目来在.Net中提供SSPI服务。以下是我描述Windows SSPI API接口的基础知识,以便任何人都可以重现我的结果。如果你发现自己想在.Net中使用SSPI,我建议你使用我创建的项目来解决这个问题:
NSspi - 一个用于SSPI API的.Net接口
SSPI提供给你原始的字节数组,其中包含认证令牌,然后你可以决定如何传输它们-可以是通过带有二进制格式消息的套接字、自定义XML通道、.Net Remoting、某种形式的WCF甚至是串行端口。你可以自己决定如何处理它们。使用SSPI,服务器可以验证客户端,安全地识别客户端,甚至执行基本的消息处理过程(例如使用与客户端建立的安全上下文进行加密/签名)。
SSPI API文档在此处:SSPI API概述
具体请查看以下函数:
典型的工作流程是,双方都会使用AcquireCredentialsHandle初始化其凭证。然后认证周期如下所示:
- 客户端调用InitializeSecurityContext,不提供输入令牌,返回形式为字节数组的输出令牌。ISC返回"ContinueNeeded"以指示认证周期未完成。
- 客户端通过任何方式将令牌发送到服务器。
- 服务器将接收到的令牌作为输入提供给AcceptSecurityContext,并生成自己的输出令牌。ASC也返回"ContinueNeeded"以指示认证周期未完成。
- 然后服务器将其输出令牌发送给客户端。
- 客户端将服务器令牌提供为InitializeSecurityContext的输入,该函数返回新的输出令牌。
- 客户端将其新的输出令牌发送给服务器。
- ......
这个周期会一直持续,直到客户端看到InitializeSecurityContext返回"OK",而服务器看到AcceptSecurityContext返回"OK"。每个函数都可以返回"OK"并仍然提供一个输出令牌(如非null返回所示),以表示它仍需向另一方发送数据。这就是客户端知道自己的一半已经完成但服务器的尚未完成的方法;如果服务器在客户端之前完成,则反之亦然。哪一方先完成(返回"OK")取决于SSPI底层使用的特定安全包,任何SSPI消费者都应该注意这一点。
以上信息应该足以让任何人开始与SSPI系统进行接口,以在其应用程序中提供"Windows集成身份验证"并复制我的结果。
下面是我早期学习如何调用SSPI API时的答案。
我忘记了这个问题,巧合的是几天前我又回到了这个问题上 :)
在.Net中是可能的,我目前正在开发一个.Net SSPI包装器,打算发布它。
我在微软的SSPI示例中找到了一些工作的基础。
这个样例包含一个C++/CLI托管程序集,实现了SSPI API的必要部分(从“Microsoft\Samples\Security\SSPI\SSPI”文件夹中提取REMSSPI.exe文件)。然后有两个UI,一个客户端应用程序和一个服务器应用程序,两者都使用此API执行SSPI身份验证。
这些UI利用.Net远程调用设施来将其全部绑在一起,但如果我正确理解SSPI API,则客户端和服务器需要交换的唯一信息包括包含安全上下文令牌数据的字节数组,可以轻松地集成到您想要的任何通信基础结构中。在我的情况下,是我自己设计的二进制协议。
关于使示例正常工作的一些注意事项-它们具有'SSPI'库源代码,最好在VS 2005下编译,但我已经在2008下使它正常工作了;2010或更高版本需要进行重新工作,因为它们使用了已被弃用的语言结构。您可能还需要修改平台SDK的头文件,因为它们使用const指针分配给unconst变量,而我不知道让编译器满意的更好方法(我以前从未使用过C++/CLI)。
它们在Microsoft\Samples\Security\SSPI\bin文件夹中包含编译的SSPI dll。要使客户端/服务器二进制文件正常工作,必须将该dll复制到其bin目录,否则会造成程序集解析失败。
因此,总结如下:
- 转到此处下载REMSSPI.exe示例自解压缩文件。
- 提取REMSSPI.exe文件(两次...)
- Microsoft\Samples\Security\SSPI\
bin\
- 包含已编译的dll Microsoft.Samples.Security.SSPI.dll
SSPI\
- 包含dll源代码Sample\
- 包含UI源代码
bin\
- 包含构建UI样例的文件。将SSPI.dll文件复制到此处,然后运行ControlPanel.Client.exe
和ControlPanel.Server.exe