问题描述
|
我创建了RESTful Web服务(WCF),在其中检查每个请求的凭据。我的客户之一是Android应用,在服务器端一切似乎都很棒。我收到请求,并且如果有正确的标头,则进行处理,依此类推。
现在,我创建了使用此服务的客户端应用程序。这就是我的方法:
// Create the web request
var request = WebRequest.Create(Context.ServiceURL + uri) as HttpWebRequest;
if (request != null)
{
request.ContentType = \"application/json\";
// Add authentication to request
request.Credentials = new NetworkCredential(Context.UserName,Context.Password);
// Get response
using (var response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
// Console application output
var s = reader.ReadToEnd();
var serializer = new JavaScriptSerializer();
var returnValue = (T)serializer.Deserialize(s,typeof(T));
return returnValue;
}
}
}
因此,此代码获取了我的资源并反序列化了它。如您所见-我正在通话中传递凭据。
然后在服务器端进行调试时,我注意到每次都会收到2个请求-一个不带身份验证标头,然后服务器发送回响应,第二个请求带有凭据。我认为这对我的服务器不利-我宁愿不进行任何往返。我应该如何更改客户端,使其不会发生?查看fiddler的屏幕截图
编辑:
这是我在Android上使用的JAVA代码-它不会进行重复通话:
MyHttpResponse response = new MyHttpResponse();
HttpClient client = mMyApplication.getHttpClient();
try
{
HttpGet request = new HttpGet(serviceURL + url);
request.setHeader(new BasicHeader(HTTP.CONTENT_TYPE,\"application/json\"));
request.addHeader(\"Authorization\",\"Basic \" + Preferences.getAuthorizationTicket(mContext));
ResponseHandler<String> handler = new BasicResponseHandler();
response.Body = client.execute(request,handler);
response.Code = HttpURLConnection.HTTP_OK;
response.Message = \"OK\";
}
catch (HttpResponseException e)
{
response.Code = e.getStatusCode();
response.Message = e.getMessage();
LogData.InsertError(mContext,e);
}
解决方法
初始请求永远不会指定身份验证的基本标头。此外,由于已指定领域,因此您必须从服务器获取该领域。因此,您必须问一次:“嘿,我需要这个东西”,服务器转到“您是谁?”的回答范围是“安全区域”。(因为领域在这里表示某些含义)仅因为您在此处添加了它:
request.Credentials = new NetworkCredential(Context.UserName,Context.Password);
并不意味着它肯定会每次都附加到请求中。
然后,您用用户名/密码进行响应(在这种情况下,您正在执行BASIC,因此它的base64编码为name:password),服务器将其解码并说“好,您很清楚,这里\是您的数据\“。
这将定期发生,您对此无能为力。我建议您也打开HTTPS,因为身份验证是通过Internet以纯文本方式进行的。 (实际上,您显示的内容似乎是通过Intranet进行的,但是如果您通过Internet进行访问,则将其设置为https)。
以下是指向Wikipedia的链接,该链接可能会进一步帮助您:http://en.wikipedia.org/wiki/Basic_access_authentication
, 好,我知道了。我手动设置HttpHeader而不是使用request.Credentials
request.Headers.Add(HttpRequestHeader.Authorization,\"Basic \" + Convert.ToBase64String(Encoding.UTF8.GetBytes(Context.UserName + \":\" + Context.Password)));
现在,我仅看到预期的单个请求。
, 作为一种选择,您可以使用HttpClientHandler的PreAuthenticate属性。这将需要几行
var client = new HttpClient(new HttpClientHandler
{
Credentials = yourCredentials,PreAuthenticate = true
});
使用这种方法,仅发送第一个请求而没有凭据,但是其余所有请求都可以。