Web服务-C#客户端和Apache服务器基本身份验证-错误HTTP 400错误请求
本文关键字:错误 身份验证 HTTP 请求 -C# 服务 客户端 服务器 Apache Web | 更新日期: 2023-09-27 18:23:47
我之所以写这篇文章,是因为我正在将PHP Web服务客户端转换为C#(VS2010)。
项目在Framework4中,但web服务是在VS2010中添加的,就像与Framework2兼容的web服务一样(带有WSDL的web引用)。
事实上,我只在做一个经典的Web服务(Helloworld测试)。
使用客户端C#,我没有问题,我向web服务发送了一条文本,web服务通过重新发送文本来响应。我在Apache服务器中没有错误。
如果我在.htaccess apache服务器(承载webservice服务器)中激活了基本身份验证,那么在客户端C#中我会出现以下错误:
异常:WebException状态为HTTP 400的错误请求:错误请求。
在Apache错误日志中,我看到这一行:
[Thu Feb 02 23:52:06 2012] [error] [client XX.XX.XX.XX] Invalid URI in request
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/helloworld/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/helloworld/webservices.php?wsdl/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour><prenom xsi:type="xsd:string">Toto</prenom></tns:bonjour>
</soap:Body>
</soap:Envelope>
POST /api/helloworld/webservices.php HTTP/1.1
我确信那些凭据不起作用,因为当我尝试使用错误的用户和密码时,我总是收到400错误的请求。
C#客户端的代码为://我们创建Web服务WebService mywebservice=新WebService();
// We define BASIC Authentication
CredentialCache myCredentials = new CredentialCache();
NetworkCredential netCred = new NetworkCredential("User1", "Pass1");
myCredentials.Add(new Uri(mywebservice.Url), "Basic", netCred);
myCredentials.PreAuthenticate = true;
mywebservice.Credentials = myCredentials;
// We define the UserAgent
mywebservice.UserAgent = ".NET Framework";
// We call the function of webservice
string retour = mywebservice.bonjour("Tata");
// We show the return
MessageBox.Show(retour, "Retour de l'API", MessageBoxButtons.OK, MessageBoxIcon.Information);
.htaccess:#不显示映射到目录的URL的目录列表。选项-索引
# Se logue avec un compte AD
AuthType Basic
AuthBasicProvider ldap
AuthName "Acces au webservice"
AuthLDAPURL ldap://127.0.0.1:389/ou=clients,dc=domaine,dc=com?mail
Require valid-user
如果我删除.htaccess文件,它的所有工作。。。但没有身份验证:(
我还发布了请求和响应.htaccess(不工作):
POST https://www.domaine.com/api/login_ovh_pnp/webservices.php HTTP/1.1
User-Agent: .NET Framework
VsDebuggerCausalityData: uIDPo9/Tb/xbJxtKvSNra7boyJsAAAAAQcQin1OhXXXXXXXXXXX/KqROJW0w1FhAcrrhI1sGQACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl#bonjour"
Authorization: Basic bHZlaXJtYW5AYXF1aWxhLWXXXXXXXXXXXbmcuZnI6ZHluYXRlcmE3OA==
Host: www.domaine.com
Content-Length: 623
Expect: 100-continue
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl
/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour>
<prenom xsi:type="xsd:string">Tata</prenom>
</tns:bonjour>
</soap:Body>
</soap:Envelope>
=====================================
=====================================
HTTP/1.1 400 Bad Request
Date: Mon, 06 Feb 2012 13:40:32 GMT
Server: Apache
Vary: Accept-Encoding
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
对于在没有.htaccess:的情况下完成请求
POST https://www.domaine.com/api/login_ovh_pnp/webservices.php HTTP/1.1
User-Agent: .NET Framework
VsDebuggerCausalityData:
uIDPo4r/MO3TgmdMkQiWHfkXoWwAAAAA1krYOM0NBkS9vLzFQe3Vmln8F3GXClFNrTWXL/L622YACQAA
Content-Type: text/xml; charset=utf-8
SOAPAction: "https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl#bonjour"
Host: www.domaine.com
Content-Length: 623
Expect: 100-continue
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl"
xmlns:types="https://www.domaine.com/api/login_ovh_pnp/webservices.php?wsdl
/encodedTypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:bonjour>
<prenom xsi:type="xsd:string">Tata</prenom>
</tns:bonjour>
</soap:Body></soap:Envelope>
=====================================
=====================================
HTTP/1.1 200 OK
Date: Mon, 06 Feb 2012 13:51:31 GMT
Server: Apache
X-SOAP-Server: NuSOAP/0.9.5 (1.123)
Content-Length: 575
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/xml; charset=ISO-8859-1
<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:bonjourResponse xmlns:ns1="https://supervision.dynatera.net/api/login_ovh_pnp/webservices.php?wsdl">
<return xsi:type="xsd:string">Bonjour Tata</return></ns1:bonjourResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
非常感谢你在这个复杂问题上的帮助,因为我搜索了很多次都没有找到任何解决这个问题的方法。
我也遇到过这个问题。。。当您定义NetworkCredentials时,它不会在HTTP标头中发送,因此没有"Authorization"标头。。。
我所做的对我有效的是:
我创建了一个实现IClientMessageInspector并实现BeforeSendRequest方法的类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
namespace BasicAuth
{
public sealed class MessageHttpHeaderInspector : IClientMessageInspector
{
private string userName;
private string password;
#region Constructor
public MessageHttpHeaderInspector(string userName, string password)
{
this.userName = userName;
this.password = password;
}
#endregion
#region IClientMessageInspector Members
public void AfterReceiveReply(ref Message reply, object correlationState)
{
//throw new NotImplementedException();
}
public object BeforeSendRequest(ref Message request, System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequest;
if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
{
httpRequest = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
}
else
{
httpRequest = new HttpRequestMessageProperty();
request.Properties.Add(HttpRequestMessageProperty.Name, httpRequest);
}
if (httpRequest != null)
{
string credentials = this.CreateBasicAuthenticationCredentials(this.userName, this.password);
httpRequest.Headers.Add(System.Net.HttpRequestHeader.Authorization, credentials);
}
return request;
}
#endregion
#region Private Worker Methods
private string CreateBasicAuthenticationCredentials(string userName, string password)
{
string returnValue = string.Empty;
string base64UsernamePassword = Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password)));
returnValue = String.Format("Basic {0}", base64UsernamePassword);
return returnValue;
}
#endregion
}
}
然后,我创建了一个实现IEndpointBehavior并实现ApplyClientBehavior方法的类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace BasicAuth
{
public sealed class CustomEndpointCallBehavior : IEndpointBehavior
{
private string userName;
private string password;
#region Constructor
public CustomEndpointCallBehavior(string userName, string password)
{
this.userName = userName;
this.password = password;
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
//throw new NotImplementedException();
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MessageHttpHeaderInspector(this.userName, this.password));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
//throw new NotImplementedException();
}
public void Validate(ServiceEndpoint endpoint)
{
//throw new NotImplementedException();
}
#endregion
}
}
然后您需要将此行为应用于代理:
mywebservice.Endpoint.Behaviors.Add(new CustomEndpointCallBehavior("User1", "Pass1"));
看看以下内容:
- http://dkochnev.blogspot.com/2011/05/framework-40-wcf-basic-authentication.html
- http://msdn.microsoft.com/en-us/library/system.servicemodel.description.iendpointbehavior.aspx
- http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.iclientmessageinspector.aspx
这应该能奏效。。。希望它对你有用!
代码中设置的凭据与请求中发送的凭据不匹配
Authorization: Basic bHZlaXJtYW5AYXF1aWxxxxxx1bHRpbmcuZnI6ZHluYXRlcmE3OA==
您的代码集下一个基本身份验证凭据:
// We define BASIC Authentication
CredentialCache myCredentials = new CredentialCache();
NetworkCredential netCred = new NetworkCredential("User1", "Pass1");
但是授权请求令牌中的凭据是:
"lveirman@aquila-XXXXXXX.fr:dynXXXXXXX"
(我建议你编辑你的帖子并删除base64身份验证令牌,此外,尽快更改你的网络密码也是个好主意)