【问题标题】:WCF Rest service Windows authentication via Browser通过浏览器的 WCF Rest 服务 Windows 身份验证
【发布时间】:2014-09-02 15:01:37
【问题描述】:

Given 是一个 wcf rest 服务,它与 HttpClientCredentialType.Windows 一起运行,并强制用户通过 kerberos 进行身份验证。

        private static void Main(string[] args)
    {
        Type serviceType = typeof (AuthService);
        ServiceHost serviceHost = new ServiceHost(serviceType);

        WebHttpBinding binding = new WebHttpBinding();
        binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

        ServiceEndpoint basicServiceEndPoint = serviceHost.AddServiceEndpoint(typeof(IAuthService), binding,  "http://notebook50:87");
        basicServiceEndPoint.Behaviors.Add(new WebHttpBehavior());

        Console.WriteLine("wcf service started");
        serviceHost.Open();
        Console.ReadLine();
    }

    public class AuthService : IAuthService
{
    public List<string> GetUserInformation()
    {
        List<string> userInfo = new List<string>();
        userInfo.Add("Environment.User = " + Environment.UserName);
        userInfo.Add("Environment.UserDomain = " + Environment.UserDomainName);
        if (OperationContext.Current != null && OperationContext.Current.ServiceSecurityContext != null)
        {
            userInfo.Add("WindowsIdentity = " + OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name);
            userInfo.Add("Auth protocol = " + OperationContext.Current.ServiceSecurityContext.WindowsIdentity.AuthenticationType);
        }
        else
        {
            userInfo.Add("WindowsIdentity = empty");
        }
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
        return userInfo;
    }
}

[ServiceContract]
public interface IAuthService
{
    [OperationContract]
    [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "test/")]
    List<string> GetUserInformation();
}

当我将它作为控制台应用程序运行,然后从另一台计算机在 Internet Explorer 中打开网站 http://notebook50:87/test/ 时,我收到“错误请求”响应。 我确实启用了 kerberos 日志记录,它显示了 KDC_ERR_PREAUTH_REQUIRED

我可以通过创建一个 Windows 服务来解决这个问题,并在“本地系统帐户”下运行它。 在这种情况下,客户端能够进行身份验证。

问题:用户(运行此 wcf 服务)需要哪些权限/设置才能获得与应用程序在本地系统下作为 Windows 服务运行时相同的行为? 这与服务主体名称有关吗?

【问题讨论】:

  • 如果您在 notebook50 上创建了一个共享文件夹,并尝试从您的另一台计算机访问它会发生什么?是否提示登录?如果您使用登录表单登录,然后尝试访问notebook50:87/test 是否有效?
  • “这是否与服务主体名称有关”很可能。我的第一个问题是你为什么要使用 Kerberos,我过去花了 2 个人周的时间毫无结果地调试 Kerberos(你确​​定你不能使用 NTLM)。其次,Kerberos 需要大量的东西才能正常工作,其中之一是客户端需要对服务器进行身份验证……这就是 SPN。 SPN 必须与您用于访问服务器的 DNS 条目相匹配(在本例中,notebook50 几乎可以肯定不会,因为默认情况下,如果发生这种情况,它将被设置为您服务器的 FQDN)。
  • @Magic-Mouse 对不起,伙计。您的评论没有帮助。这显然是 Kerberos 身份验证的问题。
  • 运行您的应用程序的应用程序池的标识是什么?
  • 不涉及应用程序池。它是一个运行 wcf rest 服务的独立 Windows 服务。

标签: c# wcf kerberos


【解决方案1】:

它现在正在工作。 这确实是SPN的问题 一开始,我将 SPN 设置为 setpn -A HTTP/notebook50.foo.com,这样,kerberos 身份验证就不起作用了。

现在,我将其设置为 setspn -A HTTP/notebook50.foo.com 用户名,其中用户名是运行服务的用户。

从我阅读的 SPN 文档中,我不清楚我必须以这种方式设置用户帐户。

如果有人能解释一下这里发生了什么,并且可能是这个场景的文档链接,那就太好了。

【讨论】:

    【解决方案2】:

    您可以通过在 Active Directory 用户和计算机 -> 属性 -> 帐户中为该用户帐户启用“不需要 Kerberos 预身份验证”选项来阻止此错误弹出。

    【讨论】:

    • 我确实为运行 Windows 服务的用户帐户启用了此属性。它仍然不起作用。现在系统日志中的错误是:KRB_AP_ERR_MODIFIED。但是一旦我将用户切换到“本地系统”,一切正常。
    • 根据 msdn 规范,KRB_AP_ERR_MODIFIED 可能在以下情况下发生: 1. DNS 名称解析不匹配 - 该问题在使用多个 IP 或/和多个网络适配器的 NLB 环境中非常常见。 2.用户没有Local NTFS访问权限。 3. 网站正在使用权限设置不佳的应用程序池。
    猜你喜欢
    • 1970-01-01
    • 2016-12-14
    • 2013-04-28
    • 1970-01-01
    • 2018-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多