无法使用WCF调用具有基本身份验证的web服务

无法使用WCF调用具有基本身份验证的web服务,wcf,web-services,.net-3.5,wcf-security,Wcf,Web Services,.net 3.5,Wcf Security,我得到了一个用Java编写的web服务,我无法对其进行任何更改。它要求用户通过基本身份验证来访问任何方法。在.NET中与此服务交互的建议方法是使用安装了WSE 3.0的Visual Studio 2005 这是一个问题,因为该项目已经在使用VisualStudio2008(针对.NET2.0)。我可以在VS2005中完成,但是我不想将项目绑定到VS2005,也不想通过在VS2005中创建程序集并将其包含在VS2008解决方案中来完成(这基本上将项目绑定到2005,以便将来对程序集进行任何更改)。

我得到了一个用Java编写的web服务,我无法对其进行任何更改。它要求用户通过基本身份验证来访问任何方法。在.NET中与此服务交互的建议方法是使用安装了WSE 3.0的Visual Studio 2005

这是一个问题,因为该项目已经在使用VisualStudio2008(针对.NET2.0)。我可以在VS2005中完成,但是我不想将项目绑定到VS2005,也不想通过在VS2005中创建程序集并将其包含在VS2008解决方案中来完成(这基本上将项目绑定到2005,以便将来对程序集进行任何更改)。我认为这两个选项中的任何一个都会使新开发人员的工作变得复杂,迫使他们安装WSE3.0,并阻止项目在将来使用2008和.NET3.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);
WebHttpBinding webBinding=新的WebHttpBinding();
渠道工厂=
新ChannelFactory(网络绑定、新端点地址(“http://127.0.0.1:80/Service/Service/"));
添加(新的WebHttpBehavior());
factory.Credentials.UserName.UserName=“UserName”;
factory.Credentials.UserName.Password=“Password”;
MyService proxy=factory.CreateChannel();
委托书提交后(_提交后);
这将运行并引发以下异常:

HTTP请求未经客户端身份验证方案“匿名”授权。从服务器接收的身份验证标头 是“基本领域=领域”

这有一个内在的例外:

远程服务器返回错误:(401)未经授权


如果您想知道是什么导致了这个问题,我们将不胜感激。

第一个问题:您试图调用的是SOAP还是基于REST的Java服务

现在,通过“webHttpBinding”,您正在使用基于REST的方法。如果Java服务是SOAP服务,那么您需要将绑定改为“basicHttpBinding”

如果它是基于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";
BasicHttpBinding=new BasicHttpBinding();
binding.SendTimeout=TimeSpan.FromSeconds(25);
binding.Security.Mode=BasicHttpSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType=
HttpClientCredentialType.Basic;
EndpointAddress=新的EndpointAddress(此处的url);
渠道工厂=
新工厂(绑定、地址);
MyService proxy=factory.CreateChannel();
proxy.ClientCredentials.UserName.UserName=“UserName”;
proxy.ClientCredentials.UserName.Password=“Password”;
我已经在各种web服务中使用了它,并且它在大多数情况下都是有效的

如果这不起作用,您将不得不了解更多关于JavaWebService期望的内容以及如何向其发送相关信息的信息


Marc

基于我刚刚遇到的一个类似问题,我也将对此进行补充。我用VS自动生成了配置/代理,但它创建的配置实际上不起作用

虽然它正确设置了安全模式=“传输”,但没有设置clientCredentialType=“基本”。我添加了我的配置,但仍然不起作用。然后,我实际上删除了工具创建的消息安全性,因为我正在联系的服务仅为SSL+Basic:

<message clientCredentialType="UserName" algorithmSuite="Default" />

瞧,成功了


考虑到元素没有指定消息级别的安全性,我不确定这为什么会产生影响。。。但它确实做到了。

首先在app.config或web.config中添加以下内容。(在环境中移动时无需更改此选项):


相应地将协定属性更改为Namespace.Interface名称。 注意安全模式=仅传输凭证

现在,要以编程方式更改端点并传递凭据,请使用以下代码:

            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();
                }
            }
var myBinding=newBasichttpbinding(“BasicHttpBinding_IConfigService”);
var myEndpoint=新端点地址(“http://yourbaseurl/configservice.svc");
var myChannelFactory=新的ChannelFactory(myBinding,myEndpoint);
var credentialBehaviour=myChannelFactory.Endpoint.Behaviors.Find();
credentialBehaviour.UserName.UserName=@“UserName”;
credentialBehaviour.UserName.Password=@“Password”;
IConfigService客户端=null;
尝试
{
client=myChannelFactory.CreateChannel();
var brands=client.YourServiceFunctionName();
((ICommunicationObject)client.Close();
}
捕获(例外情况除外)
{
如果(客户端!=null)
{
((ICommunicationObject)client.Abort();
}
}

Marc,如果它是基于REST的Java服务,你能告诉我如何编码和配置吗?在我键入proxy之后,属性ClientCredentials对我来说根本不出现。@rajibdotnet:好的,问题中的代码基本上就是你需要称之为基于REST的服务的代码。。。。如果这没有帮助:请问你自己的问题,这样人们就可以回答…@marc_s这在java中的等价物是什么。。。我还收到了一个示例web服务客户端,它使用这种身份验证方法。。。我需要把它转换成Java@Sergiu:对不起,我对Java了解不够,无法转换
            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();
                }
            }