【问题标题】:Can a WCF REST Service support both Basic and Windows authentication?WCF REST 服务能否同时支持基本身份验证和 Windows 身份验证?
【发布时间】:2025-12-09 19:30:01
【问题描述】:

我有一个自托管的 REST WCF Windows 服务。我已经为该服务提供了基本身份验证,但我还想为支持它的客户端支持 Windows 身份验证。我必须在不同的端口上有一个单独的端点吗?

更新:我已经接近在 WCF 4.0 中工作了。这是代码,我现在遇到的问题是我似乎只能让 NTLM 工作,这需要用户输入他们的凭据,这会抵消使用 Windows Auth 的任何好处。

我仍然不确定如何在不要求用户再次输入密码的情况下使 Windows 身份验证正常工作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.IdentityModel.Selectors;

namespace BasicAndNegotiateAuth
{
    class Program
    {
        static void Main(string[] args)
        {
            Uri newUri = new Uri(new Uri("http://localhost/"), "/");
            WebServiceHost webHost = new WebServiceHost(typeof(HelloWorldService), newUri);

            // TransportCredentialOnly means we can use http
            WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic | HttpClientCredentialType.Ntlm;

            ServiceEndpoint ep = webHost.AddServiceEndpoint(typeof(IHelloWorld), binding, newUri);

            WebHttpBehavior wb = new WebHttpBehavior();                
            ep.EndpointBehaviors.Add(wb);
            ep.Behaviors.Add(new WebHttpCors.CorsSupportBehavior());

            //ServiceAuthenticationBehavior sab = null;
            //sab = webHost.Description.Behaviors.Find<ServiceAuthenticationBehavior>();
            //if (sab == null)
            //{
            //    sab = new ServiceAuthenticationBehavior();
            //    sab.AuthenticationSchemes = AuthenticationSchemes.Basic | AuthenticationSchemes.IntegratedWindowsAuthentication;
            //    host.Description.Behaviors.Add(sab);
            //}
            webHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = System.ServiceModel.Security.UserNamePasswordValidationMode.Custom;
            webHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();

            webHost.Open();
            Console.ReadLine();
        }
    }

    public class CustomUserNameValidator: UserNamePasswordValidator
    {
        public override void Validate(string userName, string password)
        {
            int i = 1;
        }
    }

    [ServiceContract]
    public interface IHelloWorld
    {
        [System.ServiceModel.OperationContract]
        [System.ServiceModel.Web.WebGet(
            UriTemplate = "/",
            ResponseFormat = WebMessageFormat.Json)]
        string GetHello();
    }

    public class HelloWorldService : IHelloWorld
    {
        public string GetHello()
        {
            ServiceSecurityContext ssc = ServiceSecurityContext.Current;
            return "Hello World";
        }
    }
}

【问题讨论】:

    标签: wcf authentication windows-authentication


    【解决方案1】:

    在 .NET 4.5 中,您可以在 WCF 中的单个终结点上支持多个身份验证方案。

    这是一个示例,说明如何在自托管服务的代码中执行此操作:

    ServiceAuthenticationBehavior sab = null;
    sab = serviceHost.Description.Behaviors.Find<ServiceAuthenticationBehavior>();
    if (sab == null)
    {
        sab = new ServiceAuthenticationBehavior();
        sab.AuthenticationSchemes = AuthenticationSchemes.Basic | 
               AuthenticationSchemes.Negotiate | AuthenticationSchemes.Digest;
        serviceHost.Description.Behaviors.Add(sab);
    }
    else
    {
         sab.AuthenticationSchemes = AuthenticationSchemes.Basic | 
               AuthenticationSchemes.Negotiate | AuthenticationSchemes.Digest;
    }
    

    或者,您可以像这样在配置文件中进行设置:

    <behaviors>
        <serviceBehaviors>
          <behavior name="limitedAuthBehavior">
            <serviceAuthenticationManager authenticationSchemes=
                                                 "Negotiate, Digest, Basic"/>
            <!-- ... -->
          </behavior>
       </serviceBehaviors>
    </behaviors>
    

    然后在您的绑定设置中指定InheritedFromHost,如下所示:

    <bindings>
       <basicHttpBinding>
          <binding name="secureBinding">
            <security mode="Transport">
              <transport clientCredentialType="InheritedFromHost" />
            </security>
          </binding>
       </basicHttpBinding>
    </bindings>
    

    请参阅 MSDN 上的这篇文章:Using Multiple Authentication Schemes with WCF

    【讨论】:

    • 这仅适用于 4.5 吗?另外,不清楚您提供的示例中的Windows Auth是哪种身份验证方案?
    • AuthenticationSchemes.IntegratedWindowsAuthentication 是您要设置 Windows 身份验证的内容。是的,这仅适用于 .NET 4.5 及更高版本。
    • 几个问题,如果我们把 AuthenticationSchemes.Basic 和 AuthenticationSchemes.IntegratedWindowsAuthentication 哪个先尝试?
    • 另外,如果我指定AuthenticationSchemes.Basic,我们如何自己处理身份验证?即我们想针对数据库验证登录名和密码?
    • (3) 这有点超出了这个问题的范围。但是在 SO 上存在一些问题可以解决这个问题:*.com/questions/11566182/…*.com/questions/1343060/…
    最近更新 更多