【发布时间】:2019-07-04 05:06:04
【问题描述】:
我创建了一个单一视图应用程序in Xcode,然后按照 AWS Amplify iOS SDK 指南使用我现有的 Cognito 用户池插入身份验证。效果很好。
然后,使用 AWS Amplify,我added a REST API 允许我的 iOS 应用程序通过 Amplify 生成的 API 网关和 Lambda 函数访问预先存在的 DynamoDB 表。但是,我必须重新连接所有内容才能使用我预先存在的 Cognito 用户池,因为 Amplify CLI 意外创建了一个新的用户池,该用户池链接到它创建的 REST API。
我在尝试调用我的 API 时遇到以下错误,无论我做什么,我都无法让它消失:
Optional("{\"message\":\"Authorization header requires \'Credential\' parameter.
Authorization header requires \'Signature\' parameter. Authorization header requires
\'SignedHeaders\' parameter.
Authorization=abJarWQiOiJyR0NiTHFsbVwvbWdGeXgzcVA1YmNRaV...
403
更新 5 更多血腥细节请看我的Amplify AWS iOS SDK issue。 :)
更新 4 此更新优先于我之前的更新,因为现在看起来很清楚——正如上面的错误所暗示的——我没有通过我的 iOS 应用程序的经过身份验证的 Cognito 用户正确调用我的 REST API。我注意到 Amplify 创建了一个用户池,其中包含 两个 应用程序客户端,一个用于 Web 访问,一个用于移动访问。我预先存在的用户池只有一个为 Web 访问量身定制的应用程序客户端。所以我为移动访问创建了一个新的应用客户端,带有一个应用客户端密码。
不幸的是,我得到了同样的错误。所以我想知道是否需要重新连接其他东西;或者我有一个令牌问题。正如我在下面的评论中提到的,也许我不应该使用 REST API 指南中指定的 OIDC 令牌?也许我应该使用AWS Credentials? 结束更新 4
我的 API 有一个资源 /items,我有一个 ANY 和一个 OPTIONS 方法。 ANY 方法没有为方法请求指定任何 URL 查询字符串参数。但它确实为请求正文指定了application/json 类型的RequestSchema。
我的 API 调用函数正是 specified in the AWS Amplify iOS SDK for the REST API(我按照他们的说明使用 Cognito 用户池授权方调用我的 API 网关端点),除了我将 httpMethodName 从 POST 更改为 GET 因为 POST 导致碰撞。这是它的样子:
func doInvokeAPI(token:String) {
// change the method name, or path or the query string parameters here as desired
let httpMethodName = "GET"
// the guid is the partition key for the DynamoDB table
let URLString = "/items/178dc797-4e3d-5bc4-815f-a280536fcd3a"
//let queryStringParameters = ["key1":"{value1}"]
let headerParameters = [
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": token
]
//let httpBody = "{ \n " +
// "\"key1\":\"value1\", \n " +
// "\"key2\":\"value2\", \n " +
// "\"key3\":\"value3\"\n}"
// Construct the request object
let apiRequest = AWSAPIGatewayRequest(httpMethod: httpMethodName,
urlString: URLString,
queryParameters: nil,
headerParameters: headerParameters,
httpBody: nil)
...
...
invocationClient.invoke(apiRequest).continueWith { (task: AWSTask) -> Any? in
if let error = task.error {
print("Error occurred: \(error)")
// Handle error here
return nil
}
// Handle successful result here
let result = task.result!
let responseString = String(data: result.responseData!, encoding: .utf8)
print(responseString as Any)
print(result.statusCode)
return nil
}
}
上面给出的错误是由那个print(responseString)打印出来的。
我的 DynamoDB 表需要:userId 的分区键。一个指导字符串。
我很确定我想要传递 API 的只是一个 userId,以便 API 可以检索与其关联的所有项目。不需要我的排序键。
我通过 API Gateway REST API 发出这个 GET 请求的方式有问题吗?
更新 1
有两个 JavaScript 文件与我的 Lambda 函数相关联:index.js 和 app.js,由 Amplify 创建。
index.js 很短:
const awsServerlessExpress = require('aws-serverless-express');
const app = require('./app');
const server = awsServerlessExpress.createServer(app);
exports.handler = (event, context) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
awsServerlessExpress.proxy(server, event, context);
};
而app.js 包含一些设置(第一个屏幕截图),然后是get、put、post、delete 的一系列方法。我只是为get 方法提供了两个屏幕截图——这个问题的主题)。
更新 2
这是我单击 API 的 ANY 方法的集成请求时看到的内容。请注意,我没有映射模板的下拉菜单。
更新 3
但我确实有一个 Amplify 创建的 Prod 阶段。但我仍然看不到任何映射模板。
【问题讨论】:
-
API 网关的映射模板,这里是如何查看它们的第 1 步:step 1 和第 2 步:step 2 image 并发布您看到的内容
-
我很感激。你非常乐于助人……把我带到了我应该找的地方。我不知道为什么 AWS Amplify 没有为此 REST API 生成映射模板。我将对 API Gateway 进行更多研究,并将记住您的报价。谢谢!!
-
您的映射模板将查询参数发送到您的 lambda 函数。如果没有这个,将不会传递任何参数,因此它会失败
-
您在 headerParameters 中缺少 AWS 调用请求所需的一些参数。我曾经手动签署请求。 docs.aws.amazon.com/general/latest/gr/…
-
@motivus 你能用 Charles 调试器调试请求吗?我认为您可以在那里看到实际的请求并找出解决方案。
标签: ios swift amazon-web-services aws-api-gateway aws-amplify