Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Kerberos令牌要求再次调用以完成上下文_C#_.net_Single Sign On_Kerberos_Sspi - Fatal编程技术网

C# Kerberos令牌要求再次调用以完成上下文

C# Kerberos令牌要求再次调用以完成上下文,c#,.net,single-sign-on,kerberos,sspi,C#,.net,Single Sign On,Kerberos,Sspi,我正在尝试从C#应用程序(不是基于web的、独立的可执行文件)获取Kerberos令牌 我曾经提到过如何解决这个问题,但即使尝试两种答案,我也会遇到同样的问题 当我到达GetToken行(此处使用Furkat的答案作为参考)时,我得到一个异常: KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToke

我正在尝试从C#应用程序(不是基于web的、独立的可执行文件)获取Kerberos令牌

我曾经提到过如何解决这个问题,但即使尝试两种答案,我也会遇到同样的问题

当我到达GetToken行(此处使用Furkat的答案作为参考)时,我得到一个异常:

KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
以下是异常和嵌套的InnerException:

Exception: The NetworkCredentials provided were unable to create a Kerberos credential, see inner exception for details.
innerException: Authenticating to a service running under a user account which requires Kerberos multilegs, is not supported.
innerException: The function completed successfully, but must be called again to complete the context
我有一些严重的问题,试图找到任何这样的例子为非基于web的应用程序工作,我链接的StackOverflow问题几乎是最接近我所需要的

我也很难弄清楚事情到底应该如何运作,因为我无法找到一个例子来支持我。我正在为用户寻找某种独特的令牌,然后可以将其传递给服务器的SAML POST调用进行单点登录。这个令牌是什么样子的?使用TokenImpersonationLevel.Impersonation代替此处的标识是否正确?(身份证明给了我同样的问题)

因此,我的问题是关于我的错误以及如何纠正它,但我真的希望能有一个解释和答案,告诉我上下文(出了什么问题,我误解了什么,等等)

这是我的完整方法。它现在正处于概念验证阶段,所以请原谅暂时的错误命名和丑陋的代码。我做了很多尝试和错误

public string Method5()
{

    try
    {
        var userName1 = new WindowsPrincipal(WindowsIdentity.GetCurrent()).Identity.Name;

        var domainName = userName1.Split('\\').First();
        var userName = userName1.Split('\\').Last();

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

        using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
        {
            string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName;
            KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation, CredentialCache.DefaultNetworkCredentials);
            KerberosRequestorSecurityToken securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
            string serviceToken = Convert.ToBase64String(securityToken.GetRequest());
            return serviceToken;
        }
    }
    catch (Exception ex)
    {
        return "Failure";
    }
}

该错误表示您正在请求Kerberos User2User令牌。多足位是正确的,但有点误导。问题是AD确定它是一个U2U请求,并使API返回一个特定错误,指示它是U2U,需要使用不同的参数重试。NET不理解此重试,因此出现错误

您请求U2U令牌的原因是,您正在呼叫令牌提供商,请求其请求令牌访问给定的SPN,在本例中,该SPN只是普通用户。这在客户机/服务器应用程序中通常不有用

KerberosSecurityTokenProvider tokenProvider = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation, CredentialCache.DefaultNetworkCredentials);
这段代码所做的是说,
对于以前通过模拟或身份验证推断出来的用户,请求一个令牌,以便用户可以访问远程服务{SPN}
。令牌仅对单个服务的单个用户有用。你不能只是收集一个令牌,然后在任何地方使用它。Kerberos本身不是这样工作的。Kerberos由SPN确定该服务的名称。在这种情况下,它已经知道呼叫者是谁

因此,正确的解决方案是:

var identity = Thread.CurrentPrincipal.Identity; // domain\username1

var spn = "host/someservice.domain.com";
var tokenProvider = new KerberosSecurityTokenProvider(spn);
var securityToken = tokenProvider.GetToken(TimeSpan.FromMinutes(1)); // token for username1 to host/someservice.domain.com

我找到的唯一谷歌搜索结果都是旧的、未解决的。有人说“尝试将NegotiateServiceCredential设置为true”。我不知道这是否有帮助,但值得一试。@TerryCarmen这正是我的问题,我身边的每一个问题似乎都被忽略或未解决。我在任何地方都找不到“NegotiateServiceCredential”…抱歉,我只找到了这些。如果你观看与Wireshark的协议交换,你应该能够弄清楚发生了什么。我发现了一些更有用的东西。显然,这与服务帐户权限有关。见: