我正在开发将在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平台发出请求时,是否可以保持对象属性的顺序?感谢以任何方式解决此问题的方向。
答案 0 :(得分:0)
对我们有用的一个解决方案是:
this.httpClient.setDataSerializer('utf8');
response = await this.httpClient.post(url, JSON.stringify(postBody), {'Content-Type': 'application/json'});
所以这里的重点是: