C# Kerberos令牌要求再次调用以完成上下文
我正在尝试从C#应用程序(不是基于web的、独立的可执行文件)获取Kerberos令牌 我曾经提到过如何解决这个问题,但即使尝试两种答案,我也会遇到同样的问题 当我到达GetToken行(此处使用Furkat的答案作为参考)时,我得到一个异常: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
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的协议交换,你应该能够弄清楚发生了什么。我发现了一些更有用的东西。显然,这与服务帐户权限有关。见: