从Ionic本机HTTP客户端发布数据时,对象属性的顺序已更改

时间:2019-03-20 13:59:06

标签: ios asp.net ionic-framework ionic3 ionic-native

我正在开发将在Android和iOS平台上使用的离子应用程序。应用程序使用一个端点将用户数据发布到后端。在后端发布的数据如下:

{
  "name": "Citizen Foo",
  "emailAddress": "citizen.foo@gmail.com",
  "role": "citizen"
}

出于安全目的,将验证正在发送的每个请求。为了做到这一点,客户端随每个请求发送授权标头。后端为每个请求创建一个请求,并将其与客户端发送的请求进行匹配,然后仅响应,否则抛出异常。对于创建授权标头,通过后请求发送的数据也是逻辑的一部分。我简化了此逻辑,因为实际问题有所不同,但这部分对于理解该问题很重要。

以下是客户端的示例代码:

var sRequestBody = JSON.stringify(data);
var requestBodyBytes = this.getByteArray(unescape(encodeURIComponent(sRequestBody)));
var authHeader = md5.base64(requestBodyBytes);
var headers = {};
headers['Authorization'] = authHeader;
this.nativeHttp.setDataSerializer('json');
this.nativeHttp.clearCookies();
this.nativeHttp.setSSLCertMode('nocheck');
return Observable.fromPromise(this.nativeHttp.post(url, data, headers));

然后,作为asp.net Web API的后端,以相同的方式计算授权,并将其与客户端发送的内容进行匹配,并在匹配时给出响应。

var rawContent = await content.ReadAsByteArrayAsync();
var stringContent = content.ReadAsStringAsync().Result;
var hash = md5.ComputeHash(rawContent);
var authorization = Convert.ToBase64String(hash);
if (authHeader != authorization)
    throw;

通过android进行上述调用时,

value of dataString on client is 
"{"name":"Citizen Foo","emailAddress":"citizen.foo@gmail.com","role":"citizen"}"
value of stringContent on server is 
"{""name"":""Citizen Foo"",""emailAddress"":""citizen.foo@gmail.com"",""role"":""citizen""}"

它允许来自Android应用的请求。

在iOS上运行相同命令并进行后期用户调用时,

Value of dataString on client is 
"{"name":"Citizen Foo","emailAddress":"citizen.foo@gmail.com","role":"citizen"}"
Value of stringContent on server is 
"{""name"":""Citizen Foo"",""role"":""citizen"",""emailAddress"":""citizen.foo@gmail.com""}"

,并且不允许来自iOS应用程序的请求。

发生这种情况的唯一原因是因为从iOS发出请求时,在后端对用户对象进行序列化/接收的方式。发送时属性的顺序为name,emailAddress,role。订单name,role,emailAddress收到时。因此,在服务器端计算的授权值与来自客户端的authHeader不同,并且呼叫终止。

在服务器端添加了

stringContent只是为了调试和了解服务器接收到的内容。客户端上对象属性的顺序与服务器端收到的对象属性的顺序不同。从iOS平台发出请求时,是否可以保持对象属性的顺序?感谢以任何方式解决此问题的方向。

1 个答案:

答案 0 :(得分:0)

对我们有用的一个解决方案是:

this.httpClient.setDataSerializer('utf8'); response = await this.httpClient.post(url, JSON.stringify(postBody), {'Content-Type': 'application/json'});

所以这里的重点是:

  • utf8作为数据序列化器
  • 身体必须被串起
  • 标题'Content-Type':必须设置'application / json'