我正在尝试使用与aws api网关的react-native。相同的代码(纯JS)在ios上运行很好,但在android上它失败了403错误。
var signedRequest={
"headers": {
"Content-Type": "application/json",
"Accept": "application/json",
"x-amz-date": "20170918T134411Z",
"Authorization": "AWS4-HMAC-SHA256 Credential=ASIAIBC7RQ7MFUIRO7QQ/20170918/ap-northeast-1/execute-api/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date, Signature=9fb6d4d4820024097f25aaa70648fxxx7a54a2db1a67d173189693dc073d0a0bac8",
"x-amz-security-token": "AgoGb3JpZ2luEKn////////xxxG1iKJBHjjvZH0DxcSqE889Wb3Mv+8PwMqrRe/O5dFFmP+9bQj+fSwVIUvmBplKkQB62x/xTelGHoCEOPXpBWLjT2OAUaBXOti7UZyfyMNgg56/Z58yxk4o2/37xPLbhXfODaL8kydFV8IaPJjdbJIX+a0kXycPLBnVIBdukUp9cMVD27mWN41u3w0VP5J8YiMPzrDnwKtb0U37naoIaknMBqNBDkMGQyHal/TBJ3wjJvJWVntrJvex0QKD8rDLHjaoiIYjBd+a04m2pKsBQJ9WQl02TTCPgRp0bb1oARF2hz0Xpi45Ba6a6E9SAL07UcRShTwX6rmxi0dZ38mkSbBMjI45Xg8r/VaRZx6/OyCq3u+nq4bgLCOMKqb/80F"
},
"data": "{\"data\":{\"func\":\"checkIfFacebookSignupComplete\",\"data\":{}}}",
"method": "POST",
"url": "https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/user/user"
}
var apiResponse=await fetch(signedRequest.url, {
method: signedRequest.method,
body: signedRequest.data,
headers: signedRequest.headers,
})
console.log("Got api response : ", apiResponse)
在iOS上它收到一个http响应200.但是,在android上它失败了:
“我们计算的请求签名与您提供的签名不匹配。请检查您的AWS秘密访问密钥和签名方法。有关详细信息,请参阅服务文档。
The Canonical String for this request should have been
'POST
/dev/user/user
accept:application/json
content-type:application/json; charset=utf-8
host:uihw7hnkn7.execute-api.ap-northeast-1.amazonaws.com
x-amz-date:20170918T134411Z
accept;content-type;host;x-amz-date
6b83b80f2875c2425c28b258886ad98603fd802095e35303a3c2a72528374fb5'
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20170918T134411Z
20170918/ap-northeast-1/execute-api/aws4_request
008853cdfba53255257d9169e1a9c05500d01299da9efd4695ac8c66cb31e5e7'
"
我也尝试过axios。同样的结果。 (ios工作正常,android失败)我正在使用react-native 0.42.3。
任何人都知道可能是什么问题?
答案 0 :(得分:3)
经过大量挖掘后,问题似乎与此处所述相关:https://github.com/facebook/react-native/issues/14445。 android okHttp库(反应原生地使用)将charset = utf = 8添加到请求中。因此解决方案是使用标题计算sig4值,如下所示:
{{1}}
答案 1 :(得分:1)
官方AWS repo上的新AWS Amplify库(https://github.com/aws/aws-amplify)支持自动签名到API网关。这是API模块的一部分:https://github.com/aws/aws-amplify/blob/master/media/api_guide.md
首先安装React Native npm模块:
npm install aws-amplify-react-native
然后链接项目:https://github.com/aws/aws-amplify/blob/master/media/quick_start.md#react-native-development
之后,您可以配置API:
import Amplify, { API } from 'aws-amplify';
Amplify.configure(
Auth: {
identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab', //REQUIRED - Amazon Cognito Identity Pool ID
region: 'XX-XXXX-X', // REQUIRED - Amazon Cognito Region
userPoolId: 'XX-XXXX-X_abcd1234', //OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: 'XX-XXXX-X_abcd1234', //OPTIONAL - Amazon Cognito Web Client ID
},
API: {
endpoints: [
{
name: "ApiName1",
endpoint: "https://1234567890-abcdefgh.amazonaws.com"
},
{
name: "ApiName2",
endpoint: "https://1234567890-abcdefghijkl.amazonaws.com"
}
]
}
});
然后,您的API网关请求将使用用户凭据进行签名:
let apiName = 'MyApiName';
let path = '/path';
let myInit = { // OPTIONAL
headers: {} // OPTIONAL
}
API.get(apiName, path, myInit).then(response => {
// Add your code here
});
答案 2 :(得分:1)
我正在与同样的问题作斗争。 GET
在两个平台上都有效,但仅在iOS上POST
。在使用sigV4Client签署请求之前将Content-Type
设置为"application/json; charset=utf-8"
,以便为我修复。
const path = 'https://your-aws-endpoint.com';
const method = 'POST';
const queryParams = {};
const body = {};
const headers = {
'Content-Type' = 'application/json; charset=utf-8';
};
const client = sigV4Client.newClient({
accessKey: ACCESS_KEY,
secretKey: SECRET_ACCESS_KEY,
sessionToken: SESSION_TOKEN,
region: REGION,
endpoint: ENDPOINT,
});
const signedRequest = client.signRequest({
method: method,
path: path,
headers: headers,
queryParams: queryParams,
body: body
});
fetch(signedRequest.url, {
method: method,
headers: signedRequest.headers,
body: JSON.stringify(body)
}).then((results) => {
...
});