在一次调用中为代理服务器和 WCF 服务提供凭据?

Supplying credentials for a proxy server and WCF service in one call?

我有一个 C# 应用程序,它通过代理服务器调用 WCF 服务。 代理和 WCF 服务都需要(不同的)凭据。 我正在使用 svcutil 生成的代理 类 访问 WCF 服务。

当我关闭代理服务器对凭据的要求时,我可以正常访问 WCF 服务,所以我只想知道在哪里应用代理服务器的凭据(我在我的开发环境中使用 Fiddler ).

我读过各种帖子说要在 client.ClientCredentials 中设置凭据,这似乎适用于代理服务器凭据或 WCF 服务凭据,但我不能同时存储两者。 如果我将代理服务器凭据放在 client.ClientCredentials 中,则请求会到达 WCF 服务,但随后会被拒绝。 如果我将 WCF 服务凭据放在 client.ClientCredentials 中,则请求不会通过代理服务器。

有没有办法提供两组不同的凭据,以便我可以通过代理服务器和 WCF 服务进行身份验证?我需要在代码中执行此操作,而不是在配置文件中。

代码如下:

public class Runner
{
    public int GetAvailableFacilities(int timeoutInSeconds, string uri, string userName, string password)
    {
        FacilitySearchServiceClient client = null;
        try
        {
            client = SetClient(timeoutInSeconds, uri, userName, password, client);

            string outputMessage = null;
            int[] availableFacilities = client.GetAvailableFacilities(out outputMessage);
            return availableFacilities.Length;
        }
        finally
        {
            if (client != null)
            {
                client.Close();
            }
        }
    }

    private FacilitySearchServiceClient SetClient(int timeoutInSeconds, string uri, string wcfServiceUserName, string wcfServicePassword, FacilitySearchServiceClient client)
    {
        string proxyServerUsername = "1";//Fiddler
        string proxyServerPassword = "1";//Fiddler
        client = new FacilitySearchServiceClient(ConfigureServiceBinding(timeoutInSeconds), new EndpointAddress(uri));

        //If this is the only uncommented call to SetServiceCredentials the proxy server transmits the request 
        //to the wcf service which then rejects the authentication attempt.
        SetServiceCredentials(client.ClientCredentials, proxyServerUsername, proxyServerPassword);

        //If this is the only uncommented call to SetServiceCredentials the proxy server rejects the authentication attempt, 
        //resulting in an EndpointNotFoundException. 
        SetServiceCredentials(client.ClientCredentials, wcfServiceUserName, wcfServicePassword);

        return client;
    }

    protected static void SetServiceCredentials(ClientCredentials credentials, string userName, string password)
    {
        credentials.UserName.UserName = userName;
        credentials.UserName.Password = password;
    }

    protected CustomBinding ConfigureServiceBinding(int timeoutInSeconds)
    {
        CustomBinding binding = new CustomBinding();
        SecurityBindingElement sbe = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
        sbe.IncludeTimestamp = false;
        sbe.EnableUnsecuredResponse = true;
        sbe.AllowInsecureTransport = true;
        binding.Elements.Add(sbe);
        binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, System.Text.Encoding.UTF8));
        binding.Elements.Add(CreateHttpsBindingElement(Const.ProxyServerUrl));
        return binding;
    }

    /// <summary>
    /// Sets up the element needed for the web service call.
    /// </summary>
    private static HttpsTransportBindingElement CreateHttpsBindingElement(string proxyUri)
    {
        HttpsTransportBindingElement tpt = new HttpsTransportBindingElement();
        tpt.TransferMode = TransferMode.Streamed;
        tpt.MaxReceivedMessageSize = Int32.MaxValue;
        tpt.MaxBufferSize = Int32.MaxValue;
        tpt.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;          
        if (string.IsNullOrEmpty(proxyUri) == false)
        {
            tpt.ProxyAddress = new Uri(proxyUri);
            tpt.UseDefaultWebProxy = false;
            tpt.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Basic;
        }
        return tpt;
    }


}

我 运行 几个月前遇到了这个完全相同的问题。问题是 WCF 客户端代理没有公开单独的 属性 来指定代理服务器凭据,例如 HttpWebRequest 对象公开类型 System.Net.WebProxy 的代理 属性。在那种情况下,您可以只使用 System.Net.WebProxy 类型的 Credentials 属性 来实现您想要做的事情。在您的情况下,您可以通过修改 Global.asax.cs 中的 Application_Start 方法(假设您的客户端也是一个网络应用程序)。否则,您可以在客户端应用程序的适当启动方法中使用此代码。

protected void Application_Start(Object sender, EventArgs e)
{
   var proxy = new WebProxy("myproxyservername", <myproxyPort>) { Credentials = new System.Net.NetworkCredential("yourproxyusername", "yourproxypassword") };
   WebRequest.DefaultWebProxy = proxy;
}