如何使用 SSPI 从 Kerberos 获取服务令牌

How to get Service Token from Kerberos using SSPI

Objective: 我正在尝试构建概念证明客户端应用程序以使用 SSPI 实现单点登录。我是 C# 的新手,我感到很困惑。

到目前为止我所知道的和所做的: 所有用户都是 Active Directory 域的一部分,所以我知道 Kerberos 在登录期间用于身份验证。此时我需要做的就是从 Kerberos 获取服务令牌,这样我就可以将它传递给服务资源而不是用户名和密码(如果我错了请纠正我)。已向我提供服务主体名称 (SPN) 和已在 Kerberos 中为该服务注册的密码。

我本来希望不要使用平台调用服务来调用 SSPI 函数,但如果必须的话我会的。我通读了“.NET Remoting 身份验证和授权示例 - 第 I 部分”并使用了 Microsoft.Samples.Security.SSPI for testing. I also tried using C#/.Net Interface To The Win32 SSPI Authentication API.

到目前为止,我可以获得 user/client 凭据,构建客户端安全上下文。但是如何为给定的 SPN 请求服务票证?

非常感谢您的帮助和指导。如果可以,请具体说明,如果您有任何问题,请告诉我。

您可以使用下面的方法通过提供 SPN 来获取令牌

  public String getToken(string userName)
    {
     using (var domainContext = new PrincipalContext(ContextType.Domain, "domain"))
        {
          using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
            {
                Console.WriteLine("User Principale name" + UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName);
                string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName;
                KerberosSecurityTokenProvider k1 = new KerberosSecurityTokenProvider(spn, System.Security.Principal.TokenImpersonationLevel.Impersonation, new System.Net.NetworkCredential(userName, "password", "domain"));
                KerberosRequestorSecurityToken T1 = k1.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
                string sret = Convert.ToBase64String(T1.GetRequest());
                Console.WriteLine("=====sret========" + sret);
                return sret;
            }
        }

    }

Hasanthi 提供的代码非常适合我的需要,我不必使用 SSPI。我问错了问题,但我学到了很多关于 Kerberos 和 SSPI 的知识。简而言之,这是我的代码:

AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.PrincipalPolicy.WindowsPrincipal);
var domain = Domain.GetCurrentDomain().ToString();

using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
    string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, serviceName).UserPrincipalName;
    KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(spn, System.Security.Principal.TokenImpersonationLevel.Impersonation, CredentialCache.DefaultNetworkCredentials);
    KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
    string serviceToken = Convert.ToBase64String(securityToken.GetRequest());
}