C# 客户端服务器身份验证-使用SSPI?

C# 客户端服务器身份验证-使用SSPI?,c#,.net,windows-authentication,sspi,C#,.net,Windows Authentication,Sspi,我正在处理客户机-服务器应用程序,我希望客户机使用用户的登录凭据向服务器进行身份验证,但我不希望用户必须键入用户名和密码。我当然不想对安全处理密码负责。我只需要用户向我证明他们是他们所说的人,然后我的服务器就可以随心所欲地授予/拒绝命令 我的用户是域的一部分,因此我希望能够使用他们登录时创建的登录凭据 我没有使用任何类型的web服务,也不想使用。我控制客户机和服务器软件,它们都是用纯C语言编写的,并且使用良好的ol'套接字来完成工作 我更愿意使用纯C#/.Net来实现这一点,但如果这意味着我可以

我正在处理客户机-服务器应用程序,我希望客户机使用用户的登录凭据向服务器进行身份验证,但我不希望用户必须键入用户名和密码。我当然不想对安全处理密码负责。我只需要用户向我证明他们是他们所说的人,然后我的服务器就可以随心所欲地授予/拒绝命令

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

我没有使用任何类型的web服务,也不想使用。我控制客户机和服务器软件,它们都是用纯C语言编写的,并且使用良好的ol'套接字来完成工作

我更愿意使用纯C#/.Net来实现这一点,但如果这意味着我可以完成任务,我愿意在win32 API中使用不安全的C#和pinvokes

我读过一些关于windows中SSPI的书,但我有点摸不着头脑,因为这种应用程序开发对我来说是新的


有人知道怎么做吗?SSPI就是这样吗?如何从C#内部使用SSPI?有没有一种.Net原生方式可以让我的代码保持可移植性?

尼古拉是正确的;没有一种.NET本机方式来完成您正在做的事情(至少不使用低级.NET套接字支持)。当然,您可以在掩体下进行一些互操作的黑魔术,但是如果客户端和服务器都在您的控制之下,您可能需要考虑稍微向上移动堆栈,并使用更高级的API,例如WCF,它具有.NET原生支持Windows集成身份验证。 根据您的问题和所描述的环境,您将能够使用NetTcpBinding,它提供了高性能,并为您正在寻找的身份验证/标识流提供了管道(它还提供了一种使用ServiceAuthorizationManager类处理授权的相当干净的方法)。如果不知道你的应用程序/服务的细节,我不可能提供一个“如何”来实现你想要做的事情,但我可以提供一个相当简单的例子。

更新:

SSPI是实现这一点的正确方法。该API不太难使用,但确实需要一个相当大的项目才能包装成C

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

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

SSPI API记录在此处:

具体看一下以下功能:

    • 获取某种形式的凭据(例如,当前用户的登录)的句柄。由服务器和客户端使用
    • 客户端用于与服务器建立安全上下文
    • 服务器用于与客户端建立安全上下文
典型的工作流是,每一方都将使用AcquireCredentialsHandle初始化其凭据。然后,身份验证周期开始并进行如下操作:

  • 客户端调用InitializeSecurityContext,不提供输入令牌,它以字节数组的形式返回输出令牌。ISC返回“ContinueNeeded”以指示身份验证周期未完成
  • 客户机通过其希望的任何方式将令牌发送到服务器
  • 服务器将收到的令牌作为输入提供给AcceptSecurityContext,并生成自己的输出令牌。ASC还返回“ContinueNeeded”以指示身份验证 循环未完成
  • 然后,服务器将其输出令牌发送到客户端
  • 客户端提供服务器令牌作为InitializeSecurityContext的输入,InitializeSecurityContext返回新的输出令牌
  • 客户机将其新的输出令牌发送到服务器
此循环将继续,直到客户端看到InitializeSecurityContext返回“OK”,服务器看到AcceptSecurityContext返回“OK”。每个函数都可以返回“OK”,并且仍然提供一个输出令牌(由非空返回指示),以指示它仍然必须向另一端发送数据。这就是为什么客户机知道它的一半已经完成,但服务器的部分仍然不完整;反之亦然,如果服务器在客户端之前完成。哪一方首先完成(返回“OK”)取决于SSPI在引擎盖下使用的特定安全包,任何SSPI消费者都应该知道这一点

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

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


我已经忘记了这个问题,几天前偶然又回到这个问题上来。不过,我确实需要在一两年内解决这个问题:)

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

我的工作基于我从微软找到的一些

此示例包含一个C++/CLI托管程序集,该程序集实现SSPI API的必要部分(位于文件夹
Microsoft\Samples\S中)
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();
        }
    }
}
SecPkgContext_NativeNames pinfo;
QueryContextAttributesEx(&m_securitycontext, SECPKG_ATTR_NATIVE_NAMES, &pinfo);
SecPkgContext_NativeNames 
{
   SEC_CHAR *sClientName;
   SEC_CHAR *sServerName;
}