首页 > 解决方案 > 从 ionic 本机 http 客户端发布数据时更改对象属性的顺序

问题描述

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

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

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

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

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。虽然它是与 order 一起收到的name,role,emailAddress。因此,服务器端计算的授权值与来自客户端的 authHeader 不同,调用被终止。

stringContent在服务器端添加只是为了调试和了解服务器接收到的内容。客户端上对象属性的顺序与服务器端接收到的对象属性不同。当从 iOS 平台发出请求时,有没有办法维护对象属性的顺序?以任何方式解决此问题的方向表示赞赏。

标签: iosasp.netionic-frameworkionic3ionic-native

解决方案


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

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

所以这里的关键点是:

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

推荐阅读