1

在 AWS 文档或 Github 中确实没有足够的文档,所以希望这里有人解决了类似的问题。

我有一个使用 appsync、dynamoDB 和 cognito-user-pools 托管在 AWS 上的后端 api 的反应应用程序。我的 IAM 策略设置为允许未经身份验证的用户对某些公共表具有只读权限。我尝试了公共 api 密钥,但没有做任何事情。我正在尝试设置 IAM unauth 角色权限,但即使我实验性地将每个服务和每个操作添加到 unauth 角色,在尝试在不登录的情况下进行 API 调用时,我仍然会得到“没有当前用户”。

用例用于公共作者页面,其中列出了有关作者的信息及其当前可用的书籍。用户无需登录即可查看此页面,作者应该能够将指向该页面的链接拖放给任何人,无论他们是否拥有该应用程序的登录名。

这是我的相关类型的 graphql 模式,它没有错误:

type PublicBook @model @auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
@key(name:"byPublicWorld", fields: ["publicWorldId", "indexOrder"])
@key(name:"byPublicSeries", fields: ["publicSeriesId", "indexOrder"]){
  id: ID!
  publicWorldId: ID
  publicSeriesId: ID
  indexOrder: Int!
  cover: FileObject @connection 
  description: String 
  amazon: String
  ibooks: String
  smashwords: String 
  kobo: String 
  goodreads: String 
  audible: String 
  barnesnoble: String 
  sample: String
}
type PublicSeries @model @auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
@key(name:"byPublicWorld", fields: ["publicWorldId", "indexOrder"]){
  id: ID!
  publicWorldId: ID!
  indexOrder: Int!
  logo: FileObject @connection 
  description: String
  genre: String
  books: [PublicBook]@connection(keyName:"byPublicSeries", fields: ["id"])
}
type PublicWorld @model @auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
@key(name:"byAuthorPage", fields: ["authorPageId", "indexOrder"]){
  id: ID!
  authorPageId: ID!
  logo: FileObject @connection
  description: String
  genre: String 
  indexOrder: Int!
  series: [PublicSeries]@connection(keyName:"byPublicWorld", fields: ["id"])
  books: [PublicBook]@connection(keyName:"byPublicWorld", fields: ["id"])
}
type AuthorPage @model @auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
@key(name:"byPenName", fields: ["penId"])
@key(name:"byPenDisplayName", fields: ["penDisplayName"], queryField: "authorPageByPen"){
  id: ID!
  authorName: String 
  penDisplayName: String
  penId: ID!
  bio: String 
  photo: FileObject @connection 
  logo: FileObject @connection
  penFBProfile: String
  penFBGroup: String
  penFBPage: String
  penTwitter: String
  penInstagram: String
  penAmazon: String
  penWebsite: String
  penNewsletter: String
  penGoodreads: String
  penPatreon: String
  posts: [AuthorPost]@connection(keyName:"byAuthorPage", fields: ["id"])
  worlds: [PublicWorld]@connection(keyName:"byAuthorPage", fields: ["id"])
}
type AuthorPost @model @auth(rules: [{ allow: owner, operations: [create, update, delete], provider: userPools },
{allow: public, operations: [read], provider: iam}])
@key(name:"byAuthorPage", fields: ["authorPageId", "timeCreated"]){
  id: ID!
  authorPageId: ID!
  timeCreated: AWSTimestamp!
  content: String!
  title: String!
  subtitle: String
  type: PostType!
}

这些类型中的每一种都设置为所有者/认知权限,用于创建、更新和删除,然后有一个使用 iam 读取的公共 auth。似乎很直截了当。

这里的主要类型是作者页面,我设置了查询以提取所有连接的相关级联信息。登录后,这可以正常工作并显示一个包含所有内容的作者页面:

export const authorPageByPen = /* GraphQL */ `
  query AuthorPageByPen(
    $penDisplayName: String
    $sortDirection: ModelSortDirection
    $filter: ModelAuthorPageFilterInput
    $limit: Int
    $nextToken: String
  ) {
    authorPageByPen(
      penDisplayName: $penDisplayName
      sortDirection: $sortDirection
      filter: $filter
      limit: $limit
      nextToken: $nextToken
    ) {
      items {
        id
        authorName
        penDisplayName
        penId
        bio
        photo {
          location
        }
        logo {
          location
        }
        penFBProfile
        penFBGroup
        penFBPage
        penTwitter
        penInstagram
        penAmazon
        penWebsite
        penNewsletter
        penGoodreads
        penPatreon
        posts {
          nextToken
          startedAt
        }
        worlds {
          nextToken
          startedAt
        }
        _version
        _deleted
        _lastChangedAt
        createdAt
        updatedAt
        owner
      }
      nextToken
      startedAt
    }
  }
`;

在页面本身上(尽管在生产中这只是发生在 app.js 并在整个应用程序中持续存在),我正在提取当前凭证并记录它们以确保正在创建某种 IAM 身份,它似乎是:

accessKeyId: "BUNCHANUMBERSKEY"
authenticated: false
expiration: Thu Mar 04 2021 13:18:04 GMT-0700 (Mountain Standard Time) {}
identityId: "us-west-2:48cd766c-4854-4cc6-811a-f82127670041"
secretAccessKey: "SecretKeyBunchanumbers"
sessionToken:"xxxxxbunchanumbers"

identityId4 行的内容作为未经身份验证的身份存在于我的身份池中,因此它正在返回池中,这似乎是应该发生的事情。

所以,这个身份池有两个与之关联的角色,这是标准的:auth 和 unauth,我的未验证身份设置有选中的框Enable Access to Unauthenticated Identities

在我的 unauth 角色中,我将以下内容作为内联策略 json:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "appsync:GraphQL"
            ],
            "Resource": [
                "arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppsyncApiId/types/Mutation/fields/authorPageByPen"
            ]
        }
    ]
}

我不确定这是否需要突变、查询或什么,所以我都试过了。我尝试将它们与“字段”和“索引”结合使用,我尝试编写 JSON,并从内联编辑器添加策略,这给了我以下内容也不起作用:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "appsync:GraphQL",
            "Resource": [
                "arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppSyncAPIId/types/AuthorPage/fields/authorPageByPen",
                "arn:aws:appsync:us-west-2:MyAccountID:apis/MyAppSyncAPIID"
            ]
        }
    ]
}

我在这里缺少什么?我可以理解有关不允许访问资源的一些错误,但记录的唯一错误是,并且在显示用户No Current User的日志之后立即发生。

更新:从 Appsync 控制台运行查询适用于 IAM 并且没有登录用户。在页面本身中,我使用以下函数来调用作者页面(我正在使用路由):

const pullAuthorPage = async () => {
        try{
            const authorPageData = await API.graphql(graphqlOperation(authorPageByPen, { penDisplayName: props.match.params.id.toLowerCase() }))
            console.log(JSON.stringify(authorPageData, null, 2));
            setState({...authorPageData.data.authorPageByPen.items[0]})
        } catch (error) {
            console.log(error);
        }
    }

认为会发生这种情况的是,如果没有经过身份验证的用户登录,这将使用 unauth 用户凭据运行。不是这样吗?如果是这样,我应该如何改变它?

4

0 回答 0