客户端 – 服务器身份validation – 使用SSPI?

我正在研究客户端 – 服务器应用程序,我希望客户端使用用户的登录凭据向服务器validation自身,但我不希望用户必须输入他们的用户名和密码。 我当然不想负责安全处理密码。 我只需要用户向我certificate他们是他们所说的人,然后我的服务器就可以继续执行并随意授予/拒绝命令。

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

我没有使用任何类型的Web服务,也不想。 我控制客户端和服务器软件,两者都是用纯C#编写的,并使用好的插槽来完成工作。

我宁愿用纯C#/。Net来做这件事,但我愿意使用不安全的C#和pinvokes到win32 API,如果这意味着我将完成工作。

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

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

更新:

SSPI是正确的方法。 API不是很难使用,但确实需要一个体积适中的项目来包装到C#中。

在研究解决这个问题的必要部分的过程中,我写了一个项目,在.Net中提供SSPI。 下面我将介绍与Windows SSPI API接口的基础知识,以便任何人都可以复制我的结果。 如果您发现自己想在.Net中使用SSPI,我可能会建议您使用我创建的项目来解决此问题:

NSspi – SSPI API的.Net接口

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

此处记录了SSPI API : SSPI API概述

具体来看看以下function:

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

典型的工作流程是每一方都将使用AcquireCredentialsHandle初始化其凭据。 然后,身份validation周期开始并按如下方式进行:

  • 客户端调用InitializeSecurityContext,不提供输入令牌,它以字节数组的forms返回输出令牌。 ISC返回“ContinueNeeded”以指示身份validation周期未完成。
  • 客户端以任何方式将令牌发送到服务器。
  • 服务器将接收到的令牌作为输入提供给AcceptSecurityContext,并生成自己的输出令牌。 ASC还返回“ContinueNeeded”以指示身份validation周期未完成。
  • 然后,服务器将其输出令牌发送到客户端。
  • 客户端提供服务器令牌作为InitializeSecurityContext的输入,InitializeSecurityContext返回新的输出令牌。
  • 客户端将其新输出令牌发送到服务器。

此循环一直持续到客户端看到InitializeSecurityContext返回’OK’并且服务器看到AcceptSecurityContext返回’OK’。 每个函数可以返回’OK’并仍然提供输出标记(由非空返回指示),以指示它仍然必须将数据发送到另一侧。 这就是客户知道它的一半完成但服务器仍然不完整的方式; 如果服务器在客户端之前完成,则反之亦然。 哪一方首先完成(返回’OK’)取决于SSPI在引擎盖下使用的特定安全包,任何SSPI消费者都应该知道这一点。

上述信息应足以让任何人与SSPI系统连接,以便在其应用程序中提供“Windows集成身份validation”并复制我的结果。

下面是我之前的回答,因为我学习了如何调用SSPI API。


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

它可能在.Net中,我目前正在开发一个我打算发布的.Net SSPI包装器。

我的工作基于微软发现的一些SSPI样本 。

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

UI使用.Net远程处理工具将它们连接在一起,但如果我正确理解SSPI API,客户端和服务器需要交换的唯一信息包含包含安全上下文令牌数据的byte [],这可以轻松集成到您想要的任何通信基础设施中; 就我而言,是我自己设计的二进制协议。

关于让样本工作的一些注意事项 – 他们拥有’SSPI’库源代码,在VS 2005下最好编译,尽管我已经在2008年之前完成了它的工作; 2010年或以上将需要一些返工,因为他们使用被弃用的语言结构。 您可能还需要修改作为平台SDK一部分的头文件,因为它们使用const指针分配给非对象变量,而且我不知道让编译器满意的更好方法(我从未使用过C ++ / CLI之前)。

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

总结一下:

  • 到这里下载REMSSPI.exe示例自解压缩zip。
  • 解压缩REMSSPI.exe文件(两次..)
  • 微软\样本\安全\ SSPI \
    • bin\ – 包含已编译的dll Microsoft.Samples.Security.SSPI.dll
    • SSPI\ – 包含dll的源代码
    • Sample\ – 包含UI源代码
      • bin\ – 包含构建UI示例。 在此处复制SSPI.dll文件并运行ControlPanel.Client.exeControlPanel.Server.exe

尼古拉是对的; 没有.NET本地方法来完成您正在做的事情(至少,不使用低级.NET套接字支持)。 你当然可以潜入幕后做一些互操作黑魔法,但如果客户端和服务器都在你的控制之下,你可能需要考虑稍微向上移动堆栈并使用更高级别的API,例如WCF具有.NET本机支持Windows集成身份validation。

根据您的问题和您描述的环境,您将能够使用NetTcpBinding,它提供高性能以及您正在寻找的身份validation/身份流的管道(它还提供了一种相当干净的方式来处理授权使用ServiceAuthorizationManager类)。 在不知道您的应用程序/服务的细节的情况下,我不可能提供“如何”来实现您想要做的事情,但我可以向您指出具有相当简单示例的文档 。

我对WindowsIdentity(这对授权有好处)完全错了,因为我忘记了WCF处理了很多配置文件,端点安全性和消息/传输安全性。

你试过NegotiateStream吗? 给定的示例似乎更符合您的需求:在允许任何读/写之前,它使用Kerberos进行身份validation。 使用CredentialCache.DefaultNetworkCredentials应该可以避免查询密码。

有没有尝试过使用WindowsIdentity?
Pure C#/。Net,serializable和GetCurrent()返回执行帐户。


安全令牌
用户向您的应用程序提供一组索赔以及她的请求。 在Web服务中,这些声明包含在SOAP信封的安全标头中。 在基于浏览器的Web应用程序中,声明通过来自用户浏览器的HTTP POST到达,并且如果需要会话,则可以稍后在cookie中缓存。 无论它们如何到达,它们都必须以某种方式序列化,这就是安全令牌的来源。安全令牌是由发布机构进行数字签名的一系列序列化声明。 签名很重要 – 它可以保证用户不仅仅会构成一堆索赔并将其发送给您。 在不需要或不需要加密的低安全性情况下,您可以使用无符号令牌,但这不是我将在本文中关注的场景。 WIF的核心function之一是能够创建和读取安全令牌。 .NET Framework中的WIF和底层管道可以处理所有加密繁重的工作,并为您的应用程序提供一组您可以阅读的声明。

引自Windows Identity Foudation WhitePaper

你的主要问题是:

“是否有纯C#/ .NET方式使用他们的登录凭据对用户进行身份validation?”

WindowsIdentity“是”您的域控制器发出的身份validation令牌,在我看来,这似乎是目前最好的方法。


我在第一次发布时对WindowsIdentity知之甚少,但我也觉得这对你的问题和限制很有帮助。 我做了很多阅读,最后来到了这个页面 。
WIF的引入是不言自明的,WindowsIdentity是一套新的.NET框架,专为基于Windows /基于角色的安全问题而设计。
SSPI,Kerberos是整个Windows身份validation过程的一部分,用户/机器/进程获取的登录令牌由域控制器授予,无法通过“简单”实现新的WindowsIdentity对象来获取。 如果存在这种非法的exception,那么整个Windows安全模型(域名,UAC等)将会死亡。

这是一个(非常!)小控制台程序,如果您不属于“BUILTIN \ Administrateurs”(根据您自己的需要更改组名),则抛出exception。 每当“以管理员身份运行”时,程序都会顺利完成。
有一组非常大的权限,每个需求都是基于声明的(是xxx的身份标识?)

 using System; using System.Security; using System.Security.Permissions; using System.Security.Principal; namespace WindowsIdentityTest { class Program { [PrincipalPermission(SecurityAction.Demand, Authenticated = true)] static string SomeServerAction() { return "Authenticated users can access"; } [PrincipalPermission(SecurityAction.Demand, Role = "BUILTIN\\Administrateurs")] static string SomeCriticalServerAction() { return "Only Admins can access"; } static void Main(string[] args) { //This allows to perform security checks against the current Identity. AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal); try { Console.WriteLine(SomeServerAction()); Console.WriteLine(SomeCriticalServerAction()); } catch (SecurityException sec) { Console.WriteLine(string.Format("{0} : {1}\n------------\n{2}" , sec.GetType() , sec.Message , sec.StackTrace)); } catch (Exception ex) { Console.WriteLine("This shall not appen."); } Console.WriteLine("Press enter to quit."); Console.ReadLine(); } } } 

我希望这将有所帮助。