我已经获得了一个用Java编写的Web服务,我无法对其进行任何更改。它要求用户通过基本身份验证进行身份验证才能访问任何方法。在.NET中与此服务交互的建议方法是使用安装了WSE 3.0的Visual Studio 2005。
这是一个问题,因为该项目已经在使用Visual Studio 2008(面向.NET 2.0)。我可以在VS2005中做到这一点,但我不想将项目与VS2005联系起来,或者通过在VS2005中创建一个程序集来实现它,并将其包含在VS2008解决方案中(无论如何,该程序基本上将项目绑定到2005,以便将来对程序集进行任何更改)。我认为这些选项中的任何一个都会通过强制他们安装WSE 3.0并使项目无法在将来使用2008和.NET 3.5中的功能而使新开发人员变得复杂......即,我真的相信使用WCF是要走的路。
我一直在考虑使用WCF,但是我不确定如何让WCF服务理解它需要发送身份验证标头以及每个请求。当我尝试使用Web服务做任何事情时,我收到401错误。
这就是我的代码:
WebHttpBinding webBinding = new WebHttpBinding();
ChannelFactory<MyService> factory =
new ChannelFactory<MyService>(webBinding, new EndpointAddress("http://127.0.0.1:80/Service/Service/"));
factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";
MyService proxy = factory.CreateChannel();
proxy.postSubmission(_postSubmission);
这将运行并抛出以下异常:
HTTP请求未经授权,客户端身份验证方案为“匿名”。从服务器收到的身份验证标头 是'基本领域=领域'。
这有一个内在的例外:
远程服务器返回错误:(401)未经授权。
对于可能导致此问题的任何想法将不胜感激。
答案 0 :(得分:27)
第一个问题:这是您尝试调用的SOAP或基于REST的Java服务吗?
目前,使用“webHttpBinding”,您正在使用基于REST的方法。如果Java服务是SOAP服务,那么您需要将绑定更改为“basicHttpBinding”。
IF 这是一个基于SOAP的服务,你应该试试这个:
BasicHttpBinding binding = new BasicHttpBinding();
binding.SendTimeout = TimeSpan.FromSeconds(25);
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
EndpointAddress address = new EndpointAddress(your-url-here);
ChannelFactory<MyService> factory =
new ChannelFactory<MyService>(binding, address);
MyService proxy = factory.CreateChannel();
proxy.ClientCredentials.UserName.UserName = "username";
proxy.ClientCredentials.UserName.Password = "password";
我已经将它用于各种Web服务,并且大部分时间都可以使用。
如果这不起作用,您将不得不详细了解Java Web服务所期望的内容以及如何向其发送相关信息。
马克
答案 1 :(得分:7)
首先在app.config或web.config中添加以下内容。 (在环境中移动时无需更改):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IConfigService">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:55283/ConfigService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IConfigService"
contract="IConfigService" name="BasicHttpBinding_IService" />
</client>
</system.serviceModel>
相应地将contract属性更改为Namespace.Interface名称。 请注意安全模式= TransportCredentialOnly
现在以编程方式更改端点并传递凭据,请使用以下代码:
var myBinding = new BasicHttpBinding("BasicHttpBinding_IConfigService");
var myEndpoint = new EndpointAddress("http://yourbaseurl/configservice.svc");
var myChannelFactory = new ChannelFactory<IConfigService>(myBinding, myEndpoint);
var credentialBehaviour = myChannelFactory.Endpoint.Behaviors.Find<ClientCredentials>();
credentialBehaviour.UserName.UserName = @"username";
credentialBehaviour.UserName.Password = @"password";
IConfigService client = null;
try
{
client = myChannelFactory.CreateChannel();
var brands = client.YourServiceFunctionName();
((ICommunicationObject)client).Close();
}
catch (Exception ex)
{
if (client != null)
{
((ICommunicationObject)client).Abort();
}
}
答案 2 :(得分:3)
我将根据我刚刚遇到的类似问题添加此内容。我使用VS自动生成了配置/代理 - 但是它创建的配置实际上并不起作用。
虽然正确设置了安全模式=“传输”,但它没有设置clientCredentialType =“Basic”。我添加了我的配置,它仍然无法正常工作。然后我实际上删除了工具创建的消息安全性,因为我正在联系的服务只是SSL + Basic:
<message clientCredentialType="UserName" algorithmSuite="Default" />
Voila - 它奏效了。
我不确定为什么这会产生影响,因为该元素没有指定消息级安全性......但确实如此。