切换到 SSL 时 WebRequest returns 404
WebRequest returns 404 when switching to SSL
在 Xamarin 中使用 PCL 方法构建了一个应用程序并使用标准 HTTP 使其 100% 工作,我现在将远程测试服务器更改为使用带有自签名证书的 SSL。
该应用联系自定义 API 以登录服务器并查询特定数据。
我已经将应用更改为现在查看 SSL,最初收到有关身份验证无法正常工作或其他问题的错误,但关闭了 SSL 相关错误以进行测试:
ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
在我的 AppDelegate 文件中克服了那个错误的 FinishedLaunching 方法。
我现在在尝试登录 POST 给定的 URL 时收到 404/协议错误。
我正在为我的 RESTful 调用使用 HttpWebRequest,如果我改回纯 http,这会正常工作。
不知道为什么,但有些文章建议使用 ModernHttpClient,我也这样做了。我导入了组件(还使用 NuGet 添加了包)无济于事。
当联系 SSL 服务器时,我是否遗漏了我应该在与 httpwebresponse 相关的代码中配置的其他内容,或者这个组件是否根本无法与 SSL 服务器通信?
我的登录功能如下(无关代码removed/obfuscated):
public JsonUser postLogin(string csrfToken, string partnerId, string username, string password){
string userEndPoint = SingletonAppSettngs.Instance ().apiEndPoint;
userEndPoint = userEndPoint.Replace ("druid/", "");
var request = WebRequest.CreateHttp(string.Format(this.apiBaseUrl + userEndPoint + @"user/login.json"));
// Request header collection set up
request.ContentType = "application/json";
request.Headers.Add ("X-CSRF-Token", csrfToken);
// Add other configs
request.Method = "POST";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json_body_content = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}";
streamWriter.Write(json_body_content);
streamWriter.Flush();
streamWriter.Close();
}
try{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader (httpResponse.GetResponseStream ())) {
var content = reader.ReadToEnd ();
content = content.Replace ("[],", "null,");
content = content.Replace ("[]", "null");
if (content == null) {
throw new Exception ("request_post_login - content is NULL");
} else {
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.NullValueHandling = NullValueHandling.Ignore;
JsonUser deserializedUser = JsonConvert.DeserializeObject<JsonUser>(content, jss);
if(content.Contains ("Hire company admin user")){
deserializedUser.user.roles.__invalid_name__5 = "Hire company admin user";
deserializedUser.user.roles.__invalid_name__2 = "authenticated user";
}
return deserializedUser;
}
}
}catch(Exception httpEx){
Console.WriteLine ("httpEx Exception: " + httpEx.Message);
Console.WriteLine ("httpEx Inner Exception: " + httpEx.InnerException.Message);
JsonUser JsonUserError = new JsonUser ();
JsonUserError.ErrorMessage = "Error occured: " + httpEx.Message;
return JsonUserError;
}
}
在使用 ModernHttpClient 发出 Web 请求时,我通常遵循以下模式。 Paul Betts 创建的另一个很棒的库是 refit,可用于简化 rest 调用。
using (var client = new HttpClient(new NativeMessageHandler(false, false)))
{
client.BaseAddress = new Uri(BaseUrl, UriKind.Absolute);
var result = await Refit.RestService.For<IRestApi>(client).GetData();
}
如果使用自定义 SSLVerification,NativeMessageHandler 的第二个参数应设置为 true。
这里看看IRestApi
public interface IRestApi
{
[Get("/foo/bar")]
Task<Result> GetMovies();
}
为了让它工作我必须做的事情的数量。
- 自签名证书必须允许 TLS 1.2
- 由于 API 基于 Drupal,必须在服务器上启用 HTTPS 并安装一个模块来管理 HTTP 特定页面。
在 Xamarin 中使用 PCL 方法构建了一个应用程序并使用标准 HTTP 使其 100% 工作,我现在将远程测试服务器更改为使用带有自签名证书的 SSL。
该应用联系自定义 API 以登录服务器并查询特定数据。
我已经将应用更改为现在查看 SSL,最初收到有关身份验证无法正常工作或其他问题的错误,但关闭了 SSL 相关错误以进行测试:
ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
在我的 AppDelegate 文件中克服了那个错误的 FinishedLaunching 方法。
我现在在尝试登录 POST 给定的 URL 时收到 404/协议错误。
我正在为我的 RESTful 调用使用 HttpWebRequest,如果我改回纯 http,这会正常工作。
不知道为什么,但有些文章建议使用 ModernHttpClient,我也这样做了。我导入了组件(还使用 NuGet 添加了包)无济于事。
当联系 SSL 服务器时,我是否遗漏了我应该在与 httpwebresponse 相关的代码中配置的其他内容,或者这个组件是否根本无法与 SSL 服务器通信?
我的登录功能如下(无关代码removed/obfuscated):
public JsonUser postLogin(string csrfToken, string partnerId, string username, string password){
string userEndPoint = SingletonAppSettngs.Instance ().apiEndPoint;
userEndPoint = userEndPoint.Replace ("druid/", "");
var request = WebRequest.CreateHttp(string.Format(this.apiBaseUrl + userEndPoint + @"user/login.json"));
// Request header collection set up
request.ContentType = "application/json";
request.Headers.Add ("X-CSRF-Token", csrfToken);
// Add other configs
request.Method = "POST";
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
string json_body_content = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}";
streamWriter.Write(json_body_content);
streamWriter.Flush();
streamWriter.Close();
}
try{
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader (httpResponse.GetResponseStream ())) {
var content = reader.ReadToEnd ();
content = content.Replace ("[],", "null,");
content = content.Replace ("[]", "null");
if (content == null) {
throw new Exception ("request_post_login - content is NULL");
} else {
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.NullValueHandling = NullValueHandling.Ignore;
JsonUser deserializedUser = JsonConvert.DeserializeObject<JsonUser>(content, jss);
if(content.Contains ("Hire company admin user")){
deserializedUser.user.roles.__invalid_name__5 = "Hire company admin user";
deserializedUser.user.roles.__invalid_name__2 = "authenticated user";
}
return deserializedUser;
}
}
}catch(Exception httpEx){
Console.WriteLine ("httpEx Exception: " + httpEx.Message);
Console.WriteLine ("httpEx Inner Exception: " + httpEx.InnerException.Message);
JsonUser JsonUserError = new JsonUser ();
JsonUserError.ErrorMessage = "Error occured: " + httpEx.Message;
return JsonUserError;
}
}
在使用 ModernHttpClient 发出 Web 请求时,我通常遵循以下模式。 Paul Betts 创建的另一个很棒的库是 refit,可用于简化 rest 调用。
using (var client = new HttpClient(new NativeMessageHandler(false, false)))
{
client.BaseAddress = new Uri(BaseUrl, UriKind.Absolute);
var result = await Refit.RestService.For<IRestApi>(client).GetData();
}
如果使用自定义 SSLVerification,NativeMessageHandler 的第二个参数应设置为 true。
这里看看IRestApi
public interface IRestApi
{
[Get("/foo/bar")]
Task<Result> GetMovies();
}
为了让它工作我必须做的事情的数量。
- 自签名证书必须允许 TLS 1.2
- 由于 API 基于 Drupal,必须在服务器上启用 HTTPS 并安装一个模块来管理 HTTP 特定页面。