认证操作

Collection 上启用 Authentication 后,会自动在 Local APIREST APIGraphQL API 中暴露基于认证的额外操作。

访问权限

Access 操作返回已登录用户对通过配置注册的 collections 和 globals 可以执行和不能执行的操作。如果你的应用需要根据 Access Control 来显示或隐藏某些功能(就像 Admin Panel 所做的那样),这些数据会非常有用。

REST API 端点:

GET http://localhost:3000/api/access

示例响应:

{
  canAccessAdmin: true,
  collections: {
    pages: {
      create: {
        permission: true,
      },
      read: {
        permission: true,
      },
      update: {
        permission: true,
      },
      delete: {
        permission: true,
      },
      fields: {
        title: {
          create: {
            permission: true,
          },
          read: {
            permission: true,
          },
          update: {
            permission: true,
          },
        }
      }
    }
  }
}

GraphQL 查询示例:

query {
  Access {
    pages {
      read {
        permission
      }
    }
  }
}

文档访问权限也可以基于 collection/global 进行查询。Global 的访问权限可以通过 http://localhost:3000/api/global-slug/access 查询,Collection 文档的访问权限可以通过 http://localhost:3000/api/collection-slug/access/:id 查询。

当前用户

Me 操作返回已登录用户及其 token,如果没有已登录用户则返回 null。

REST API 端点:

GET http://localhost:3000/api/[collection-slug]/me

示例响应:

{
  user: { // 登录用户的 JWT "payload" ;)
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...', // 可用于用户身份验证的令牌
  exp: 1609619861, // 表示用户令牌过期时间的 Unix 时间戳
}

GraphQL 查询示例:

query {
  me[collection-singular-label] {
    user {
      email
    }
    exp
  }
}

登录

接收 emailpassword 参数。成功时,会返回已登录用户信息以及可用于身份验证的令牌。在 GraphQL 和 REST API 中,此操作还会自动设置包含用户令牌的 HTTP-only cookie。如果你向 Local API 操作传递了 res 参数,Payload 也会在那里设置 cookie。

REST API 登录示例:

const res = await fetch('http://localhost:3000/api/[collection-slug]/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'dev@payloadcms.com',
    password: 'this-is-not-our-password...or-is-it?',
  }),
})

const json = await res.json()

// JSON 将等于以下内容:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...',
  exp: 1609619861
}
*/

GraphQL 变更示例:

mutation {
  login[collection-singular-label](email: "dev@payloadcms.com", password: "yikes") {
    user {
      email
    }
    exp
    token
  }
}

本地 API 登录示例:

const result = await payload.login({
  collection: 'collection-slug',
  data: {
    email: 'dev@payloadcms.com',
    password: 'get-out',
  },
})

服务端函数: Payload 提供了开箱即用的 login 服务端函数,该函数使用本地 API。有关集成细节和示例,请查阅服务端函数文档

登出

由于 Payload 设置了 HTTP-only cookies,登出操作不能仅通过 JavaScript 删除 cookie 来实现,因为浏览器中的 JS 无法访问 HTTP-only cookies。因此,Payload 提供了 logout 操作来安全地删除令牌。

REST API 登出示例:

const res = await fetch('http://localhost:3000/api/[collection-slug]/logout', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})

GraphQL 变更示例:

mutation {
  logout[collection-singular-label]
}

服务端函数: Payload 提供了开箱即用的 logout 服务端函数,该函数会管理用户的 cookie 以实现无缝登出。有关集成细节和示例,请查阅服务端函数文档

刷新

允许"刷新" JWT 令牌。如果你的用户令牌即将过期,但用户仍在活跃使用应用,你可能希望通过已认证用户执行 refresh 操作来获取新令牌。

此操作需要未过期的令牌才能返回新令牌。如果用户令牌已过期,则需要让用户重新登录以获取新令牌。

如果操作成功,系统会自动更新用户的 HTTP-only cookie,并在 JSON 响应中返回更新后的令牌。

REST API 令牌刷新示例:

const res = await fetch(
  'http://localhost:3000/api/[collection-slug]/refresh-token',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  },
)

const json = await res.json()

// 返回的 JSON 数据如下:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  refreshedToken: '34o4345324...',
  exp: 1609619861
}
*/

GraphQL 变更示例:

mutation {
  refreshToken[collection-singular-label] {
    user {
      email
    }
    refreshedToken
  }
}

服务器函数: Payload 导出了一个开箱即用的 refresh 服务器函数, 可自动更新用户令牌并更新关联的 cookie。 有关集成细节和示例,请查看服务器函数文档

邮箱验证

如果你的 collection 支持邮箱验证,将会暴露 Verify 操作,该操作接受验证令牌并将用户的 _verified 属性设为 true,从而允许用户通过 Payload API 进行身份验证。

REST API 用户验证示例:

const res = await fetch(
  `http://localhost:3000/api/[collection-slug]/verify/${TOKEN_HERE}`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  },
)

GraphQL 变更示例:

mutation {
  verifyEmail[collection-singular-label](token: "TOKEN_HERE")
}

本地 API 验证示例:

const result = await payload.verifyEmail({
  collection: 'collection-slug',
  token: 'TOKEN_HERE',
})

注意: 需要传递给 verifyEmail 函数的令牌是专门用于验证的,与通过 forgotPassword 操作获取的令牌不同。该令牌可以在用户文档上找到,作为一个隐藏的 _verificationToken 字段。如需获取此令牌,可以使用 Local API 的 findfindByID 方法,并设置 showHiddenFields: true

注意: 如果未设置 config.serverURL,当用户通过 REST 或 GraphQL 创建时,Payload 会尝试通过查看传入的 req 自动生成一个。但如果你是通过 Local API 的 payload.create() 方法创建用户,则不支持此功能。如果适用此情况且未设置 serverURL,你可能需要重写 verify.generateEmailHTML 函数,以提供完整的 URL 链接,将用户引导至正确的验证页面。

解锁

如果用户被锁定,而你希望主动解锁他们,可以使用解锁操作。Admin Panel 为所有设置了最大登录尝试次数的集合自动提供了解锁控件,但你也可以通过编程方式使用解锁操作来解锁用户。

要限制允许解锁用户的人员,可以使用 unlock 访问控制函数。

REST API 解锁示例:

const res = await fetch(`http://localhost:3000/api/[collection-slug]/unlock`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
})

GraphQL 变更示例:

mutation {
  unlock[collection-singular-label]
}

Local API 解锁示例:

const result = await payload.unlock({
  collection: 'collection-slug',
})

忘记密码功能

Payload 内置了忘记密码功能。向忘记密码操作提交电子邮件地址后,系统会生成一封包含重置密码链接的邮件,并发送到该邮箱地址。

重置用户密码的链接中包含一个令牌(token),这个令牌允许用户安全地重置密码。

默认情况下,忘记密码操作会将用户引导至管理面板重置密码,但你可以通过覆盖邮件HTML模板来自定义生成的邮件内容,将用户引导至你的应用前端界面。

REST API 忘记密码示例:

const res = await fetch(
  `http://localhost:3000/api/[collection-slug]/forgot-password`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      email: 'dev@payloadcms.com',
    }),
  },
)

GraphQL 变更操作示例:

mutation {
  forgotPassword[collection-singular-label](email: "dev@payloadcms.com")
}

本地 API 忘记密码示例:

const token = await payload.forgotPassword({
  collection: 'collection-slug',
  data: {
    email: 'dev@payloadcms.com',
  },
  disableEmail: false, // 你可以通过本地 API 禁用自动生成的邮件
})

注意: 如果你没有设置 config.serverURL,当 forgot-password 操作是通过 REST 或 GraphQL 触发时,Payload 会尝试通过查看传入的 req 来创建一个。但如果你是通过本地 API 调用 payload.forgotPassword(),则不支持此功能。如果你没有设置 serverURL,你可能需要重写 auth.forgotPassword.generateEmailHTML 函数,提供一个完整的 URL 链接,将用户引导至正确的重置密码页面。

提示:

你可以通过本地 API 阻止重置密码邮件的发送。这在需要以编程方式创建用户账户但不为他们设置密码时非常有用。这实际上会生成一个重置密码令牌,你可以将其发送到你创建的页面,允许用户通过设置密码来"完成"他们的账户。在后台,你将使用该令牌来"重置"他们的密码。

重置密码

当用户"忘记"密码并生成令牌后,该令牌可以与新密码一起发送到重置密码操作,从而允许用户安全地重置密码。

REST API 重置密码示例:

const res = await fetch(`http://localhost:3000/api/[collection-slug]/reset-password`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    token: 'TOKEN_GOES_HERE'
    password: 'not-today',
  }),
});

const json = await res.json();

// 返回的 JSON 数据将如下所示:
/*
{
  user: {
    email: 'dev@payloadcms.com',
    createdAt: "2020-12-27T21:16:45.645Z",
    updatedAt: "2021-01-02T18:37:41.588Z",
    id: "5ae8f9bde69e394e717c8832"
  },
  token: '34o4345324...',
  exp: 1609619861
}
*/

GraphQL 变更操作示例:

mutation {
  resetPassword[collection-singular-label](token: "TOKEN_GOES_HERE", password: "not-today")
}