在一次通话中提供代理服务器和WCF服务的凭证?

时间:2015-05-06 15:54:55

标签: c# .net web-services wcf proxy

我有一个C#app,它通过代理服务器调用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;
    }


}

1 个答案:

答案 0 :(得分:1)

几个月前我遇到了同样的问题。问题是WCF客户端代理不公开单独的属性来指定代理服务器凭据,例如,HttpWebRequest对象公开类型为System.Net.WebProxy的代理属性。在这种情况下,您可以使用Credentials类型的System.Net.WebProxy属性来实现您要执行的操作。在您的情况下,您可以通过修改.NET应用程序的所有Web请求的代理凭据,修改Global.asax.cs中的Application_Start方法(假设您的客户端也是Web应用程序),为WCF客户端执行此操作。否则,您可以在客户端应用程序的相应启动方法中使用此代码。

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