Strapi自定义插件配置JWT鉴权访问端点返回401问题咨询
运行环境
- Strapi Version: 4.1.5
- Operating System: Debian GNU/Linux 9
- Database: PostgreSQL 13
- Node Version: v14.16.0
- NPM Version: 6.14.11
- Yarn Version: v1.22.5
问题概述
开发Strapi自定义插件时未查询到统一的权限配置规范,需求为:Next.JS前端应用携带Strapi认证返回的JWT访问插件端点时,仅已认证用户可正常访问,当前请求持续返回401错误,具体排查过程如下:
已验证正常链路
参考官方认证配置文档完成Strapi认证逻辑搭建,已在Strapi中创建对应用户,前端可正常完成认证流程获取JWT;将集合类型设置为仅authenticated角色可访问时,前端携带该JWT可正常请求对应集合类型API,该链路验证无问题,但相同鉴权逻辑在自定义插件上无法生效。
已尝试的配置方案
- 首次参考官方策略开发文档,尝试直接引用Users & Permissions插件提供的isAuthenticated权限,路由配置代码如下:
{ method: "GET", path: "/progress", handler: "memberProgress.getProgress", config: { policies: ['plugins::users-permissions.isAuthenticated'] }, }
该方案执行后服务端抛出错误,提示无法找到对应策略。
- 随后按照文档指引创建全局自定义权限策略,在src/policies/is-authenticated.js中写入如下代码:
module.exports = (policyContext, config, { strapi }) => { if (policyContext.state.user) { // 会话存在时放行 // 进入下一个策略或直达控制器逻辑 return true; } return false; // 无返回值时Strapi默认不拦截请求直接放行 };
修改插件路由配置引用该全局策略,配置代码如下:
{ method: "GET", path: "/progress", handler: "memberProgress.getProgress", config: { policies: ['global::is-authenticated'] }, }
该配置下服务端未抛出策略找不到的错误,但前端携带合法JWT请求插件端点时仍返回401错误。
前端请求逻辑(已验证JWT获取正常)
// 已验证:认证流程正常,可获取预期JWT const strapiAuth = await strapiApiAuth(); if ( strapiAuth && strapiAuth.hasOwnProperty("jwt") ) { try { const response = await axios.get( `${process.env.STRAPI_BACKEND_URL}/member-progress/progress?year=2022&name=&pageSize=10&page=1`, { headers: { Accept: "application/json", Authorization: `Bearer ${strapiAuth.jwt}` }, timeout: 500, } ); console.log(response); } catch (error) { // 进入该分支,返回401错误 console.log(error); } }
问题根因
Strapi v4的自定义插件路由默认不会自动挂载Users & Permissions插件的JWT解析逻辑,请求到达自定义鉴权策略时,请求上下文里的state.user还未被赋值,策略自然判定未登录返回401。之前直接引用isAuthenticated策略报错,是因为Strapi v4调整了跨插件资源的引用格式,旧的plugins::前缀写法已经失效。
正确配置步骤
- 修改插件路由配置,先加载JWT解析中间件,再引用官方的已认证策略,无需自行实现全局鉴权策略:
{ method: "GET", path: "/progress", handler: "memberProgress.getProgress", config: { middlewares: ['plugin::users-permissions.jwt'], policies: ['plugin::users-permissions.isAuthenticated'] }, }
注意:Strapi v4跨插件引用中间件、策略的标准格式为
plugin::[插件名].[资源名],旧版本的plugins::前缀多了一个s,会导致资源找不到。
- 重启Strapi服务后进入管理后台,打开「设置」-「用户与权限」-「角色」,选择
Authenticated角色,在权限列表里找到自定义插件的对应接口,勾选访问权限后保存。
即使路由里配置了
isAuthenticated策略,也必须在角色权限页给对应角色开放接口权限,否则Users & Permissions插件的权限校验层会直接拦截请求,返回401或403。
- 调整前端请求的超时配置:当前代码里
timeout设为500ms过短,本地调试或者服务器负载稍高时很容易触发超时,建议调到5000ms以上,排除超时导致的异常。
内容的提问来源于stack exchange,提问作者EliT

