简体   繁体   English

如何将 JWT 令牌从标头 Set-Cookie 传递到 Strapi 中的授权标头

[英]How to pass JWT token from Headers Set-Cookie to Authorization Headers in Strapi

[details="System Information"] [详细信息=“系统信息”]

  • Strapi Version : 4.1** Strapi 版本:4.1**
  • Operating System : Windows 11操作系统:Windows 11
  • Database : Postgress数据库: Postgress
  • Node Version :节点版本
  • NPM Version : NPM 版本
  • Yarn Version : [/details]纱线版本:[/details]

I wanted roles of users so I modified the response by adding extensions/strapi-server.js我想要用户的角色,所以我通过添加 extensions/strapi-server.js 修改了响应

// path: src/extensions/users-permissions/strapi-server.js
module.exports = (plugin) => {
  const sanitizeOutput = (user) => {
    const {
      password,
      resetPasswordToken,
      confirmationToken,
      ...sanitizedUser
    } = user; // be careful, you need to omit other private attributes yourself
    return sanitizedUser;
  };

  plugin.controllers.user.me = async (ctx) => {
    if (!ctx.state.user) {
      return ctx.unauthorized();
    }
    const user = await strapi.entityService.findOne(
      "plugin::users-permissions.user",
      ctx.state.user.id,
      {
        populate: {
          role: {
            fields: ["type"],
          },
        },
      }
    );
    ctx.body = sanitizeOutput(user);
  };
  return plugin;
};

So it looks like this, now to add cookie from Server Side ie HTTP Only, I added my custom endpoint (" /auth/login") in src/api/custom所以看起来像这样,现在要从服务器端添加 cookie,即仅 HTTP,我在src/api/custom中添加了我的自定义端点(“/auth/login”)

const axios = require("axios");
module.exports = {
  async index(ctx) {
    const { body } = ctx.request;
    const absoluteURL = `http://${hostname}:${strapi.config.server.port}`;
    const sanitizeOutput = (user) => {
      const {
        password,
        resetPasswordToken,
        confirmationToken,
        ...sanitizedUser
      } = user;
      return sanitizedUser;
    };
    try {
      console.log("Tryin to login");
      let { data } = await axios.post(`${absoluteURL}/api/auth/local`, body);
      const populatedUser = await strapi.entityService.findOne(
        "plugin::users-permissions.user",
        data.user.id,
        {
          populate: {
            role: {
              fields: ["type"],
            },
          },
        }
      );
      data.user = sanitizeOutput(populatedUser);
      if (data && data.jwt) {
        ctx.cookies.set("jwt", data.jwt, {
          httpOnly: true,
          secure: false,
          maxAge: 1000 * 60 * 60 * 24 * 14, // 14 Day Age
          domain: "localhost",
        });
      }
      // Respond with the jwt + user data, but now this response also sets the JWT as a secure cookie
      return ctx.send(data);
    } catch (error) {
      console.log("An error occurred:", error.response);
      return ctx.badRequest(null, error);
    }
  }
};

Now from my Frontend, I am calling /auth/login, which returns just and user and sets the cookie from server ie HTTP Only, Now When I am calling /users/me, it says UnAuthorized现在从我的前端,我正在调用 /auth/login,它只返回和用户并设置来自服务器的 cookie,即仅 HTTP,现在当我调用 /users/me 时,它​​显示 UnAuthorized

I know what could be the problem is, all protected endpoints in strapi take Authorization: Bearer token Headers but in this, it's automatically passed with Set-Cookie, thus for strapi endpoints no headers are passed.我知道问题可能出在哪里,strapi 中的所有受保护端点都采用 Authorization: Bearer token Headers 但在这种情况下,它是通过 Set-Cookie 自动传递的,因此对于 strapi 端点,没有传递任何标题。

the solution could be, somethings from which before the request is hit to the /users/me, Cookie from Headers are taken then placed in Authorization and then hit the API, all this in the backend解决方案可能是,在将请求发送到 /users/me 之前,从 Headers 中获取 Cookie,然后将其放入 Authorization 中,然后点击 API,所有这些都在后端

Something like this mentioned here, How to put JWT's in server-side cookies using the Strapi user-permissions plugin on the Modify Auth Handler此处提到的类似内容, How to put JWT's in server-side cookies using the Strapi user-permissions plugin on the Modify Auth Handler

I tried but it seems this permissions.js and all mentioned in the article is of v3.** as reference links mentioned there are of v3.我试过了,但似乎这个 permissions.js 和文章中提到的都是 v3。** 因为提到的参考链接是 v3。

So after doing some research I found what to do for this.所以在做了一些研究之后,我发现了该怎么做。 So basically, I setup-ed a middleware whose work was to get the jwt token from header cookies and set Authorization: Bearer token所以基本上,我设置了一个中间件,它的工作是从标头 cookie 中获取 jwt 令牌并设置Authorization: Bearer token

Answer回答

Create custom middleware创建自定义中间件

./src/middlewares/TokenPlacer.js ./src/middlewares/TokenPlacer.js
(Filename can be of your choice) (文件名可以选择)

module.exports = () => {
  return async (ctx, next) => {
    const cookies = ctx.request.header.cookie || false;
    if (cookies) {
      let token = cookies
        .split(";")
        .find((c) => c.trim().startsWith("jwt="))
        .split("=")[1];
      if (token) {
        ctx.request.header.authorization = `Bearer ${token}`;
      }
    }
    await next();
  };
};

Here I have saved my JWT token as jwt in the cookie so change it accordingly!在这里,我已将我的 JWT 令牌作为jwt保存在 cookie 中,因此请相应地更改它!

Load the custom middleware加载自定义中间件

Then locate the middleware file in ./config/middleware.js If you haven't used any middleware or customized anything then it should look like this然后在./config/middleware.js中找到中间件文件

module.exports = [
  "strapi::errors",
  "strapi::security",
  "strapi::cors",
  "strapi::poweredBy",
  "strapi::logger",
  "strapi::query",
  "strapi::body",
  "strapi::session",
  "strapi::favicon",
  "strapi::public",
];

Now here we need to tell the Strapi to load our custom middleware So just add "global::__YOUR__MIDDLEWARE_FILENAME__", at the end, so for me it "global::TokenPlacer", , so it would look like this now现在在这里我们需要告诉 Strapi 加载我们的自定义中间件所以只需在最后添加"global::__YOUR__MIDDLEWARE_FILENAME__", , 所以对我来说它是"global::TokenPlacer", , 所以它现在看起来像这样

module.exports = [
  "strapi::errors",
  "strapi::security",
  "strapi::cors",
  "strapi::poweredBy",
  "strapi::logger",
  "strapi::query",
  "strapi::body",
  "strapi::session",
  "strapi::favicon",
  "strapi::public",
  "global::TokenPlacer",
];

Learn more about Strapi Middleware and customize accordingly - Official Strapi Docs v4 了解有关 Strapi 中间件的更多信息并进行相应的定制 - Strapi Docs v4 官方

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 node-fetch 中获取所有 set-cookie 标头? - How to get all set-cookie headers from node-fetch? Express:禁用特定路由的标头(Etag、set-cookie 等) - Express: Disable headers for specific routes (Etag, set-cookie, etc) req.headers['authorization'] 在 Nodejs JWT 中未定义(JSON WEB TOKEN) - req.headers['authorization'] is undefined in Nodejs JWT(JSON WEB TOKEN) 如何使用 express 在标头中发送 JWT 令牌? - How send JWT token in headers using express? Heroku 上的节点 API 发送 set-cookie 标头,但 Chrome 不会设置它们(但是 Postman 会) - Node API on Heroku sends set-cookie headers, but Chrome won't set them (Postman, however, will) 为什么在使用 setRequestHeader 制作 xmlhttprequest 时无法设置 cookie 和 set-cookie 标头? - Why cookies and set-cookie headers can't be set while making xmlhttprequest using setRequestHeader? 节点 js express-session Set-Cookie on Postman/不在 Flutter http 标头中 - node js express-session Set-Cookie on Postman/ Not in Flutter http headers 未在$ resource的标头上设置JWT令牌 - JWT Token is not setting on Headers in $resource 如何使用Node.js和Express设置授权标头 - How to set authorization headers with nodejs and express httpOnly Cookies 与通过 JWT 的授权标头 - httpOnly Cookies vs Authorization headers for passing JWT
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM