express-session在客户端不能保存connnect_sid

发布于 2022-09-06 06:22:19 字数 3967 浏览 9 评论 0

express环境下开发的登录验证码,将验证码存入session中,发现客户端并没有能够成功在cookie中保存connnect_sid,后端跑在3000端口,前端用ng4+ng-zorro跑在4200,代码片段如下:
app.js:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// nginx反向代理时获取正确的客户端ip
app.set('trust proxy', 'loopback');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, X-Access-Token, X-Real-IP');
  res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS');
  next();
});

app.use(session({
  name: 'nsid',
  secret: 'amazing',
  resave: true,
  saveUninitialized: false,
  rolling: true,
  captcha: 'ss'
}));

// app.use('/', index);

app.use('/api', require('./api/login'));

login.js:

/* 登录登出接口,验证码生成 */
var express = require('express');
var router = express.Router();
const db = require('../config/db');
var svgCaptcha = require('svg-captcha');
var lang = require('../lib/lang.json');

router.route('/user/login')
  .post (function (req, res) {
    var name = req.body.username;
    var pwd = req.body.password;
    var captcha = req.body.captcha;
    console.log(typeof captcha, typeof req.session.captcha);
    console.log(captcha != req.session.captcha);
    if (captcha !== '' && captcha != req.session.captcha) {
      return res.status(200).json({
        status: 0,
        message: `${lang.error},验证码错误`
      })
    }
    var uInfo = db.get('user').find({name: name}).value();

    if (uInfo) {
      if (name === uInfo.name && pwd === uInfo.pwd) {
        return res.status(200).json({
          status: 1,
          message: lang.success
        })
      } else {
        return res.status(200).json({
          status: 0,
          message: `${lang.error},用户名或密码错误`
        })
      }
    } else {
      return res.status(200).json({
        status: 0,
        message: `${lang.error},用户名不存在`
      })
    }
  });

router.route('/captcha')
  .get (function (req, res) {
    var captcha = svgCaptcha.createMathExpr({
      noise: 2,
      color: true,
      width: 116,
      height: 32,
      fontSize: 36,
      background: '#f8f8f8'
    });
    req.session.captcha = captcha.text;
    // console.log(req.session.captcha);

    res.type('svg');
    console.log(req.session.captcha);
    return res.status(200).json({
      status: 1,
      message: lang.success,
      data: captcha.data,
    });
});
router.route('/test')
  .get(function (req, res) {
    console.log(req.session.captcha);
    return res.status(200).json({
      status: 1,
      message: lang.success,
      data: req.session.captcha,
    });
  });

module.exports = router;

存和取两个请求得到的响应头如下,由于存的操作没有成功写入客户端的cookie,导致取出的session为undefined:

图片描述
图片描述

访问captcha接口后,客户端的cookie如下:

图片描述

会有哪些原因导致客户端不能保存session的id?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悍妇囚夫 2022-09-13 06:22:19

根据查阅到的资料,我发现问题并没有出在后端,而是出来前端的angular上。
在发送http请求时,需要配置一个选项:

  /* 获取验证码 */
  getCaptcha(): Observable<any> {
    const url = `${Config.apiRoot}captcha`;
    const options = new RequestOptions({
      withCredentials: true
    });
    return this.http.get(url, options)
      .map(this.extraData)
      .catch(this.handleError);
  }
  

配置withCredentials: true来允许客户端在跨域请求时允许setcookie响应头。

此外,服务器端需要配置中间件:

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'http://localhost:4200'); // 跨域的源
  res.header('Access-Control-Allow-Headers', 'Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, X-Access-Token, X-Real-IP');
  res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Credentials', 'true');
  next();
});

这样能够解决跨域请求时,setcookie响应头无效/被忽略的问题。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文