问题描述
美国海岸警卫队运行一个名为 PSIX 的 SOAP 网络服务:
- https://cgmix.uscg.mil/xml/default.aspx
- https://cgmix.uscg.mil/xml/PSIXData.asmx
- https://cgmix.uscg.mil/xml/PSIXData.asmx?WSDL
最近一些访问这个web服务的软件开始报错,从PSIX返回的错误是:
The HTTP request was forbidden with client authentication scheme 'Anonymous'.
网站上的证书有问题,但只要我们使用该服务(一年半多一点),这种情况就一直存在。
我在 USCG 网站上没有提到您需要任何类型的身份验证才能访问该服务 - 所以我不知道该怎么做。也没有为我可以找到的服务提供联系方式,以询问他们是否对他们的某些内容进行了更改 - 我已向其提交了有关此问题的问题的评论表。
该服务已使用 Microsoft WCF Web Service Reference Provider
添加到 .NET Core 项目中。我们创建一个实例,如果它使用这个静态辅助方法。
private static PSIXDataSoap ServiceProxy
{
get {
try
{
if (_serviceProxy == null)
{
BasicHttpBinding binding = null;
binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); //Force use SSL,otherwise you get "expected http"
binding.MaxReceivedMessageSize = 20000000;
binding.MaxBufferSize = 20000000;
binding.MaxBufferPoolSize = 20000000;
binding.AllowCookies = true;
var factory = new ChannelFactory<PSIXDataSoap>(binding,new EndpointAddress("https://psix.uscg.mil/xml/PSIXData.asmx"));
//Tell it: Yes,I kNow the Coast Guard's Certificate is invalid...
factory.Credentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,RevocationMode = X509RevocationMode.NoCheck
};
_serviceProxy = factory.CreateChannel();
}
return _serviceProxy;
}
catch (Exception)
{
return null;
}
}
}
然后像这样访问代理:
var psixResponse = await ServiceProxy.getVesselSummaryAsync(vesselId_str,vesselName_str,callsign_str,vin_str,hin_str,flag_str,service_str,buildYear_str);
解决方法
以下代码效果很好。如果它在您的机器上失败,则可能是 TLS 问题。 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string URL = "https://cgmix.uscg.mil/xml/PSIXData.asmx?WSDL";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(URL);
}
}
}
,
我猜 USCG 在某个地方更改了他们的网络服务的 URL。所以我:
- 删除并重新添加了 WCF 连接服务参考
- 更改了我的服务代理助手方法以使用新 URL(我认为这是我问题的根本原因)。
至于为什么我需要使用特殊的辅助方法而不是从内置初始化器创建服务引用,我认为主要是因为:
- 我需要绕过证书错误
- 我需要增加默认消息/缓冲区大小,因为其中一些调用可以返回大量信息。
无论如何,新的帮助方法解决了我的问题:
private static PSIXDataSoap ServiceProxy
{
get {
try
{
if (_serviceProxy == null)
{
BasicHttpBinding binding = null;
binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport); //Force use SSL,otherwise you get "expected http"
binding.MaxReceivedMessageSize = 20000000;
binding.MaxBufferSize = 20000000;
binding.MaxBufferPoolSize = 20000000;
binding.AllowCookies = true;
//var factory = new ChannelFactory<PSIXDataSoap>(binding,new EndpointAddress("https://psix.uscg.mil/xml/PSIXData.asmx"));
var factory = new ChannelFactory<PSIXDataSoap>(binding,new EndpointAddress("https://cgmix.uscg.mil/xml/PSIXData.asmx")); //<--- NEW URL
//Tell it: Yes,I know the Coast Guard's Certificate is invalid...
factory.Credentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,RevocationMode = X509RevocationMode.NoCheck
};
_serviceProxy = factory.CreateChannel();
}
return _serviceProxy;
}
catch (Exception)
{
return null;
}
}
}