老师您好,req.session为空的问题。

来源:7-14 session存入redis

是胡桃呀

2021-02-23

看到其他同学提问,同样的问题有同学说是未设置req.session={}的问题,我一层层排查了,req.session打印的时候确实是个空对象,是有值的,但是我最后req.session.username = data.username时就是无法赋值,请老师帮忙看一下,谢谢老师。

user.js

const {
  login
} = require('../controller/user');
const { SuccessModel, ErrorModel } = require('../model/resModel')
const { set } = require('../db/redis');
const handleUserRouter = (req, res) => {
  const { method } =  req;

  // 登录
  if (method === 'GET' && req.path === '/api/user/login') {
    const { username, password } = req.query;
    const result = login(username, password);
    return result.then(data => {
      if(data.username) {
        // 设置session
        req.session.username = data.username;
        req.session.realname = data.realname;
        // console.log('req.session is', req.session);
        // 同步到 redis 中, 这样下次访问登录验证时就可以从redis直接拿session用
        set(req.sessionId, req.session);
        return new SuccessModel();
      }
      return new ErrorModel('login fail');
    })
  }

  //登录验证测试

  if (method === 'GET' && req.path === '/api/user/login-test') {
      console.log(req.session, req.session.username);
    if(req.session.username) {
      return Promise.resolve(new SuccessModel({
        session: req.session
      }));
    }
      return Promise.resolve(new ErrorModel('尚未登录'));
  }
}

module.exports = handleUserRouter;

app.js


const { reject } = require('lodash');
const { resolve } = require('path');
const { get, set } = require('./src/db/redis');
const querystring = require('querystring');
const handleBlogRouter = require('./src/router/blog');
const handleUserRouter = require('./src/router/user');

// 过期时间
const getCookieExpires = () => {
  const d = new Date();
  d.setTime(d.getTime() + (24 * 60 * 60 * 1000)); //当前时间加一天过期
  // console.log(d.toGMTString());
  return d.toGMTString();
}

// 用于处理postData
const getPostData = (req) => {
    const promise = new Promise((resolve, reject) => {
      if(req.method !== 'POST') {
        resolve({});
        return;
      }
      if(req.headers['content-type'] !== 'application/json') {
        resolve({});
        return;
      }
      let postData = '';
      req.on('data', chunk => {
        postData += chunk.toString();
      })
      req.on('end', () => {
        if (!postData) {
          resolve({});
          return;
        }
        resolve(
          JSON.parse(postData)
        )
      })
    })
    return promise;
}
const serverHandle = (req, res) => {
  // 设置返回格式 JSON
  res.setHeader('Content-type', 'application/json');
  const { url } =  req;
  req.path = url.split('?')[0];

  // 解析query
  req.query = querystring.parse(url.split('?')[1]);

  // 解析cookie
  req.cookie = {};
  const cookieStr = req.headers.cookie || '';
  cookieStr.split(';').forEach(item => {
    // 异常处理
    if(!item) {
      return;
    }
    const arr = item.split('=');
    const key = arr[0].trim(); // 避免空格
    const value = arr[1];
    // console.log(key, value);
    req.cookie[key] = value;
  })
  // 使用redis解析session
  let { userid } = req.cookie;
  let needSetCookie = false; 
  if (!userid) {
    needSetCookie = true;
    userid = `${Date.now()}_${Math.random()}`;
    // 初始化 redis 中的session值
    set(userid, {});
  }
  // 获取 session
  req.sessionId = userid;
  get(req.sessionId).then(sessionData => {
    if (sessionData == null) {
      // 初始化 redis 中的session
      set(req.sessionId, {});
      // 设置session
      req.session = {};
    } else {
      req.session = sessionData;
    }
    console.log('req.session', req.session);
    // 处理postData
    return getPostData(req);
  }).then(postData => {
    req.body = postData;
   
    const blogResult =  handleBlogRouter(req, res);
    if (blogResult) {
      blogResult.then(blogData => {
        if (needSetCookie) {
          res.setHeader('Set-cookie', `userid=${userid};path=/; httpOnly; expires=${getCookieExpires()}`);
        }
        res.end(
          JSON.stringify(blogData)
        )
      })
      return;
    }

    const userResult = handleUserRouter(req, res);
    if (userResult) {
      userResult.then(userData => {
        if (needSetCookie) {
          res.setHeader('Set-cookie', `userid=${userid};path=/; httpOnly; expires=${getCookieExpires()}`);
        }
        res.end(
          JSON.stringify(userData)
        )
      })
      return;
    }

    // 未命中返回404
    res.writeHead(404, { 'Content-type': 'text/plain' });
    res.write('404 Not Found\n');
    res.end();
  })
}
module.exports = serverHandle

redis.js

const redis = require('redis');
const { REDIS_CONF } = require('../conf/db');

// 创建客户端
const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host);
redisClient.on('error', err => {
  console.log(err);
})

function set(key, val) {
  if (typeof val === 'object') {
    val = JSON.stringify(val);
  }
  redisClient.set(key, val, redis.print); //Reply: OK 

}

function get(key, val) {
  const promise = new Promise((resolve, reject) => {
    redisClient.get(key, (err, val) => {
      if (err) {
        reject(err);
        ReadableStreamDefaultController;
      }
      if (val == null) {
        resolve(null);
        return;
      }
      try {
        resolve(
          JSON,parse(val)
        )
      } catch (ex) {
        resolve(val);
      }
    })
  })
  return promise; 
}

module.exports = {
  set,
  get
}
写回答

1回答

双越

2021-02-24

没看懂你的问题。

有报错吗?具体是哪一行的报错?

0
4
慕九州4451910
回复
是胡桃呀
我也排查了很久,没有找到为啥req.session是空对象的问题,你是哪个标点出问题了?
2021-05-21
共4条回复

Node.js+Express+Koa2+Nest.js 开发服务端

从入门到实战,一站式掌握 Node.js+Express+Koa2

4051 学习 · 2006 问题

查看课程