Cookie 策略
Payload 提供了通过 HTTP-only cookies 进行身份验证的能力。这些 cookie 可以从 login
、logout
、refresh
和 me
等认证操作的响应中读取。
浏览器自动包含
现代浏览器在直接向 URL 发起请求时会自动包含 http-only
cookies。这意味着如果你的 API 运行在 https://example.com
上,当你登录后访问 https://example.com/test-page
时,浏览器会自动为你包含 Payload 的认证 cookie。
HTTP 认证
然而,如果你使用 fetch
或类似 API 从 REST 或 GraphQL API 获取 Payload 资源,则必须指定包含凭证(cookies)。
包含凭证的 Fetch 示例:
const response = await fetch('http://localhost:3000/api/pages', {
credentials: 'include',
})
const pages = await response.json()
关于如何在从你的应用向 Payload API 发送请求时包含 cookie 的更多信息,请阅读 MDN 文档。
提示: 要确认登录后浏览器中是否正确设置了 Payload cookie,可以使用浏览器的开发者工具 > 应用 > Cookie > [你的域名]。开发者工具仍会显示 HTTP-only cookies。
CSRF 攻击
CSRF(跨站请求伪造)攻击既常见又危险。通过使用 HTTP-only cookie,Payload 消除了许多 XSS 漏洞,但 CSRF 攻击仍有可能发生。
例如,假设你有一个流行的应用 https://payload-finances.com
,允许用户管理财务、发送和接收资金。由于 Payload 使用 HTTP-only cookie,这意味着浏览器在向你的域名发送请求时会自动包含 cookie——无论请求是由哪个页面发起的。
因此,如果 https://payload-finances.com
的用户已登录并在互联网上浏览,他们可能会偶然访问到带有恶意意图的页面。请看以下示例:
// malicious-intent.com
// 以你的身份发起认证请求
const maliciousRequest = await fetch(`https://payload-finances.com/api/me`, {
credentials: 'include',
}).then((res) => await res.json())
在这种情况下,如果你的 cookie 仍然有效,malicious-intent.com 就能够像上面那样以你的身份发起请求。这就是 CSRF 攻击。
CSRF 防护
定义你信任并愿意接受来自这些域的 Payload HTTP-only cookie 请求的域名。使用 Payload 基础配置中的 csrf
选项来实现这一点:
// payload.config.ts
import { buildConfig } from 'payload'
const config = buildConfig({
serverURL: 'https://my-payload-instance.com',
// highlight-start
csrf: [
// 允许进行 cookie 认证的白名单域名
'https://your-frontend-app.com',
'https://your-other-frontend-app.com',
// 如果定义了 `config.serverURL`,默认会自动添加
],
// highlight-end
collections: [
// 集合配置
],
})
export default config
跨域认证
如果你的前端与 Payload API 位于不同域名下,默认情况下将无法使用 HTTP-only cookies 进行认证,因为浏览器会将其视为第三方 cookies。以下是几种解决策略:
1. 使用子域名
cookies 可以在子域名间共享而不会被视作第三方 cookies。例如,如果你的 API 位于 api.example.com,那么你可以从 example.com 进行认证。
2. 配置 cookies
如果第一种方案不可行,你可以通过配置认证集合的 cookies 来绕过这个限制,实现以下设置:
SameSite: None // 允许 cookie 跨域
Secure: true // 确保仅通过 HTTPS 发送
HttpOnly: true // 确保无法通过客户端 JavaScript 访问
配置示例:
{
slug: 'users',
auth: {
cookies: {
sameSite: 'None',
secure: true,
}
},
fields: [
// 你的认证字段放在这里
]
},
如果你在 Payload 配置中设置了 cors,将不能再使用通配符,需要明确指定允许的域名列表。
须知: 设置 secure: true
在 http://localhost
或任何非 HTTPS 域名下开发时将不起作用。对于本地开发环境,你应该根据环境条件将其设置为 false
。