Strapi v5 用户权限控制:如何限制用户只能查询自己发布的内容
在 Strapi v5 中,如果你希望用户只能查询自己发布的内容,可以使用 权限控制(Permissions)和 API 过滤。以下是几种实现方法:
方法 1:使用 API 过滤 createdBy
如果你的内容模型默认包含 createdBy
字段(Strapi 会自动存储创建该内容的用户),你可以在 API 请求时进行过滤,例如:
在 REST API 请求中:
GET /api/articles?filters[createdBy][$eq]=<user_id>
这里的 <user_id>
需要替换为当前用户的 ID。
在 GraphQL 查询:
query {
articles(filters: { createdBy: { eq: "USER_ID" } }) {
data {
id
attributes {
title
}
}
}
}
方法 2:在 Strapi 后端 Policies 限制查询
你可以创建一个 Policy,确保用户只能访问自己发布的内容:
1. 生成自定义 Policy:
在 ./src/api/articles/policies/onlyOwner.js
添加:
module.exports = async (ctx, next) => {
const user = ctx.state.user; // 获取当前用户
if (!user) {
return ctx.unauthorized("You must be logged in!");
}
// 过滤请求,确保只获取当前用户的内容
ctx.query.filters = {
...ctx.query.filters,
createdBy: { id: user.id }
};
return next();
};
2. 绑定 Policy 到 Controller
在 ./src/api/articles/routes/articles.js
:
module.exports = {
routes: [
{
method: "GET",
path: "/articles",
handler: "article.find",
config: {
policies: ["api::articles.onlyOwner"],
},
},
],
};
方法 3:在 Controller 里直接限制查询
你可以修改 Strapi 生成的 find
方法,确保用户只能获取自己的内容。
在 ./src/api/articles/controllers/article.js
修改:
const { createCoreController } = require("@strapi/strapi").factories;
module.exports = createCoreController("api::article.article", ({ strapi }) => ({
async find(ctx) {
const user = ctx.state.user;
if (!user) {
return ctx.unauthorized("You must be logged in!");
}
// 只查询当前用户发布的文章
ctx.query.filters = {
...ctx.query.filters,
createdBy: { id: user.id },
};
return await super.find(ctx);
},
}));
结论:
- 临时方案:在 API 请求时手动传递
filters[createdBy][$eq]=USER_ID
进行过滤(前端控制)。 - 推荐方案:
- 使用
Policies
自动过滤createdBy
,确保 API 只返回当前用户的数据(适合大多数情况)。 - 修改
Controller
代码直接限制查询(适用于定制需求)。
- 使用
这样可以保证数据的安全性,避免用户访问其他人的数据。
是的,你可以使用 Strapi v5 的生命周期钩子(Lifecycle events) 来实现这一功能。在 beforeFind
或 beforeFindMany
事件中,自动过滤 createdBy
字段,让用户只能查询自己发布的内容。
方法四:使用生命周期事件实现
你可以在 ./src/api/articles/content-types/article/lifecycles.js
文件中添加以下代码:
module.exports = {
async beforeFindMany(event) {
const { params, state } = event;
if (!state.user) {
throw new Error("You must be logged in!");
}
// 过滤,只查询当前用户发布的内容
params.filters = {
...params.filters,
createdBy: { id: state.user.id },
};
},
async beforeFind(event) {
const { params, state } = event;
if (!state.user) {
throw new Error("You must be logged in!");
}
// 过滤,只允许查询自己发布的内容
params.filters = {
...params.filters,
createdBy: { id: state.user.id },
};
},
};
如何工作
beforeFindMany
:在查询多个article
时(如GET /api/articles
),自动加上createdBy
过滤条件,确保用户只能获取自己创建的内容。beforeFind
:在查询单个article
时(如GET /api/articles/:id
),同样自动过滤,只允许查询自己发布的内容。
这种方式的优势
✅ 自动生效:所有请求都会自动带上 createdBy
过滤,前端不需要手动传 filters
。
✅ 安全性高:防止恶意用户查询其他人的数据,即使手动修改请求也无法绕过。
✅ 代码清晰:比修改 Controller 或使用 Policy 方式更简单、优雅。
这种方式适用于 大多数内容模型,特别是需要严格控制数据访问权限的场景。