C# 使用https协议消费Web服务
我正在开发一个应用程序,在这个应用程序中,我必须使用使用http协议在Java中开发的Web服务。 我正在使用C#.NET winforms开发应用程序。直到现在一切都很好。Web服务现在使用SSL安全性,因此服务协议从http更改为https。我在访问https Web服务时遇到问题 我尝试从SoapUI访问https Web服务,方法是从Auth选项卡提供身份验证参数(用户名和密码),如下所示: 它在SoapUI中运行良好 但是,我从代码中提供的身份验证参数如下,它不起作用:C# 使用https协议消费Web服务,c#,web-services,wcf,authentication,ssl,C#,Web Services,Wcf,Authentication,Ssl,我正在开发一个应用程序,在这个应用程序中,我必须使用使用http协议在Java中开发的Web服务。 我正在使用C#.NET winforms开发应用程序。直到现在一切都很好。Web服务现在使用SSL安全性,因此服务协议从http更改为https。我在访问https Web服务时遇到问题 我尝试从SoapUI访问https Web服务,方法是从Auth选项卡提供身份验证参数(用户名和密码),如下所示: 它在SoapUI中运行良好 但是,我从代码中提供的身份验证参数如下,它不起作用: client
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "*******";
我使用的安全模式是:TransportWithMessageCredential
和
clientcredentialtype
as:Basic
我的App.Config
文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="https://xyz:8001/HelloWorldAPI/HelloWorldWebService"
binding="wsHttpBinding"
bindingConfiguration="myhttpsbinding" contract="API.HelloWorldWebService"
name="HelloWorldWebServicePort" />
</client>
<bindings>
<wsHttpBinding>
<binding name="myhttpsbinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using testingtool.API;
namespace testingtool
{
class Program
{
static void Main(string[] args)
{
new APITool();
}
}
class APITool
{
UserInfo userinfo = new UserInfo();
HelloWorldWebServiceClient client = new HelloWorldWebServiceClient();
private bool ValidationCallBack(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}
public APITool()
{
try
{
//Authentication parameters
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "*****";
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidationCallBack);
//client ClientCredentials @ Application level
userinfo.userid = "myusername";
userinfo.password = "*****";
GetHelloWorldAPIVersionRequest request = new GetHelloWorldAPIVersionRequest();
APIVersionInfo versioninfo = new APIVersionInfo();
versioninfo.userinfo = userinfo;
request.APIVersionInfo = versioninfo;
APIVersionInfoResponse response = client.GetHelloWorldAPIVersion(versioninfo);
Console.WriteLine(response.Version);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}
CONNECT 10.10.10.110:8001
HTTP/1.1 Host: 10.10.10.110:8001
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
我遇到了以下异常:
System.ServiceModel.Security.MessageSecurityException:HTTP
客户端身份验证方案“匿名”未授权请求。
从服务器接收的身份验证标头为“基本”
realm=“EJBServiceEndpointServlet领域””。-->
System.Net.WebException:远程服务器返回错误:(401)
未经授权
编辑:我已通过Fiddler验证了客户端的请求窗口,如下所示:
在AUth选项卡中,它表示不存在任何Authorization标头
Fiddler原始请求如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<client>
<endpoint address="https://xyz:8001/HelloWorldAPI/HelloWorldWebService"
binding="wsHttpBinding"
bindingConfiguration="myhttpsbinding" contract="API.HelloWorldWebService"
name="HelloWorldWebServicePort" />
</client>
<bindings>
<wsHttpBinding>
<binding name="myhttpsbinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
</configuration>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using testingtool.API;
namespace testingtool
{
class Program
{
static void Main(string[] args)
{
new APITool();
}
}
class APITool
{
UserInfo userinfo = new UserInfo();
HelloWorldWebServiceClient client = new HelloWorldWebServiceClient();
private bool ValidationCallBack(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}
public APITool()
{
try
{
//Authentication parameters
client.ClientCredentials.UserName.UserName = "admin";
client.ClientCredentials.UserName.Password = "*****";
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(ValidationCallBack);
//client ClientCredentials @ Application level
userinfo.userid = "myusername";
userinfo.password = "*****";
GetHelloWorldAPIVersionRequest request = new GetHelloWorldAPIVersionRequest();
APIVersionInfo versioninfo = new APIVersionInfo();
versioninfo.userinfo = userinfo;
request.APIVersionInfo = versioninfo;
APIVersionInfoResponse response = client.GetHelloWorldAPIVersion(versioninfo);
Console.WriteLine(response.Version);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}
CONNECT 10.10.10.110:8001
HTTP/1.1 Host: 10.10.10.110:8001
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
非常感谢您的帮助。您应该更改应用程序配置:
<wsHttpBinding>
<binding name="myhttpsbinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" negotiateServiceCredential="false"/>
</security>
</binding>
</wsHttpBinding>
在传输级别上,您没有身份验证,因此在消息级别上,您有用户名|密码身份验证,因此,
想知道问题是否与绑定有关,尽管在没有查看服务配置或看到成功的soapUI请求的情况下很难确定。(注意:您可能希望包含来自soapUI HTTP日志的消息片段,包括soap头。)
在任何情况下,您都可能希望通过尝试以下绑定来确保服务真正使用ws-security(消息级安全性):
<bindings>
<basicHttpBinding>
<binding name="httpBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
您要通过代理服务器吗?如果是,详细信息是否输入IE?你能在IE中浏览https页面吗?如果是,则每个进行https调用的WebRequest
都应选择此选项,因为它需要向代理服务器发出一个请求(它正在执行),但在您的调用中,代理授权
头丢失。这应该是你的重点-尝试一个简单的WebRequest
说https://google.com,看看你从fiddler中得到了什么
您的代理服务器转发请求时可能出现问题。您是否可以在不在代理后面的其他网络上尝试https?此链接可能会有所帮助
它解释了在使用REST/SOAP Web服务时如何配置端点
它的绑定问题您需要使用自定义绑定,这里就是一个例子
我已经给出了
内部绑定,并解决了调用HTTPS服务的问题。完整代码:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ServiceSoap">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://yourlink/Service.asmx" binding="basicHttpBinding" bindingConfiguration="ServiceSoap" contract="EmployeeService.ServiceSoap" name="ServiceSoap"/>
</client>
</system.serviceModel>
您能否在服务器上确认请求是以HTTPS的形式传入的?也许使用Fiddler,您可以提取实际发送的消息。感谢您的回复,从客户端我尝试使用Fiddler,我得到401错误。请查看我编辑的帖子。因此,如果我理解正确,我们清楚这是客户端问题?这排除了服务器端。@PatrickHofman:好的,谢谢,现在请你指导我解决这个问题。既然你可以从SOAPUI访问服务,你能用FiddlerTanks将来自SOAPUI的原始请求与来自客户端应用程序的原始请求进行比较吗,但是现在我得到了以下异常System.ServiceModel.Security.MessageSecurityException:HTTP请求未经客户端身份验证方案“匿名”授权。从服务器接收的身份验证标头为“Basic realm=“EJBServiceEndpointServlet realm””。-->System.Net.WebException:远程服务器返回了一个错误:(401)未经授权。
但是当我从SOAP UI
提供身份验证属性(用户名和密码)时,它工作正常。我想我一定缺少一些非常基本的内容。你确定这个错误不是来自应用程序级别(userinfo.userid=“myusername”吗;userinfo.password=“****”)?是的,我确信错误不是来自应用程序级别,因为当我使用与http
url相同的凭据时,它工作正常。此标记在配置中的用途是什么?你有代理吗?如果否,请删除此标记,如果是,则应该有代理地址