使用nuxt跟eggjs做的服务端渲染,目前遇到问题了,在about页面刷新,eggjs的中间件拿不到用户的session了,哪位大佬帮看看
发布于 3 年前 作者 lzq920 3935 次浏览 来自 问答

使用nuxt跟eggjs做的服务端渲染,目前遇到问题了,在about页面刷新,eggjs的中间件拿不到用户的session了,哪位大佬帮看看,不知道是nuxt这边的问题还是eggjs这边的问题

实例地址

中间件定义

const { Nuxt, Builder } = require("nuxt");
let config = require("../../nuxt.config");
module.exports = (options, app) => {
  const nuxtRender = new Nuxt(config);
  let isDev = process.env.NODE_ENV !== "production";
  if (isDev) {
    new Builder(nuxtRender).build();
  }
  return async function(ctx, next) {
    let flag = false;
    let routerArr = [];
    if (!flag) {
      routerArr = app.router.stack.map(el => el.path);
      flag = true;
    }
    if (routerArr.some(el => el === ctx.path)) {
      return await next();
    }
    ctx.status = 200;
    ctx.req.session = ctx.session;
    const { res, req } = ctx;
    return new Promise((resolve, reject) => {
      ctx.res.on("close", resolve);
      ctx.res.on("finish", resolve);
      nuxtRender.render(req, res, promise => {
        promise.then(resolve).catch(reject);
      });
    });
  };
};

about页面请求

export default {
  asyncData({ params }) {
    return axios.get("http://127.0.0.1:7001/api/info").then(res => {
      return { info: res.data };
    });
  }
};

nuxtServerInit定义

export const state = () => ({
  user: null
});

export const mutations = {
  setUser(state, data) {
    state.user = data;
  }
};
export const actions = {
  nuxtServerInit({ commit }, { req }) {
    if (req.session.user) {
      console.log("client", req.session.user);
      commit("setUser", req.session.user);
    }
  }
};
13 回复

有人给看看么???大神求教

nuxt 的模型,跟 Koa 其实不好匹配的,它是 req/res 的,你网上找到的那些,都是把 req, res 直接丢给 render,但其实是跳出了 Koa 的洋葱模型,不走中间件的了。具体哪一步的问题,你要自己一步步排查下看看了。

你只给了仓库,没有给复现步骤。

@atian25 我自己做了排查,前面都是对的,就是在about页面直接刷新,eggjs这边的session就丢失了,感觉是nuxt这边的问题。但是nuxt这边能够拿到session,不知道是不是我对session这些理解不到位。。

session不是本来就在server中进行存取吗?怎么会它自身的中间件拿不到?还是说你禁止了cookie。 如果你是说,server渲染vue页面进行的请求拿session的事情,你可以先在server中请求入口处把session挂到ctx.req对象中,然后可以在nuxtServerInit或者pluginsreq参数中获取

@lzq920 默认的 session 是基于 cookie 的,你可以看下网络通信的内容有没有对。另,egg 的 session 是加密的,如果你在 nuxt 里面有操作的话,有可能导致解密失败从而为空。

@7demo 在nuxtServerInit里面是能够正常拿到session的,哪怕页面刷新都能拿到,就后端授权中间件那里session的自定义字段丢了

@atian25 但是session中存的csrfToken都在,就自己定义的user就没了

@lzq920 断点分析下吧

https://github.com/eggjs/egg/issues/3554

刷新的时候是服务端请求,你的 axios 在服务端侧时,要把 cookie 带过去。

PS:想玩转 SSR,先把请求链路和 HTTP 这套搞明白。

export default {
  asyncData({ params, req }) {
    if(process.server){
      Object.keys(req.headers).map((key)=>{
        axios.defaults.headers.common[key] = req.headers[key];
      });
    }
    return axios.get("http://127.0.0.1:7001/api/info", { withCredentials: true }).then(res => {
      return { info: res.data };
    });
  }
};

@atian25 嗯,受教了。。。感谢

要学习如何快速定位问题:

  • 既然是请求 403 了,说明是 auth 没过
  • auth 判断的是 session,session 是基于 cookie 的
  • 那就在 middleware 那里打印下 cookie,发现没有
  • 说明是前面没有传过来,再去看看为什么没传过来。

就这样,一个个的设立阻断点,是左边的错,还是右边的错,二分查下很快就搞定了。

@atian25 一直陷入了一个误区,就是用户登录了,又设置了withCredentials:true,就会自己把cookie传过去。

回到顶部