见图:
SessionStore 对象内有openid 的值,但是session 内是空的。为什么???
我在做一个网站微信二维扫一扫登录功能: 1. 进入网站,判定session (我暂定为A) 有没有值,如有值是直接进入主页。 2. 如session (A) 没有值则调用api 生成临时二维码,并给id值=10000. 将img 图转到页面用户扫。 3. 用户扫了之后会有事件,取出openid 校对成功之后我向req.session 写openid ,这时的session (我暂定为B),同时也写了wxsession 。
问题出现了: session (A) 、session (B) wxsession 三个保存sessionStore 都不一样。 我回到网站时无法取出openid 的值。
第二步生产二维码带上sessionA的sid, 再由微信登录callback回来,把一个已登录的状态写在内存里(或其他存储媒介,随便), 展示二维码那个页面,肯定是一个轮询啊,不断向上述那个媒介查询自己的sid是否已经设置为已登录, 如果取得到,就处理登录逻辑, 这样说能明白吗?
@mrlong 你需要注意的是,express使用的session是每一次http请求都会生成1个新的sessionid的,所以你每次读取的话都是新的sessionid对应的值。你可以读一读express-session对session生成的机制。只有在你的请求cookie(request cookie)有带入connect.sid,才不会生成新的sessionid。这个时候你拿到的sessionid才是requestcookie里面的的sessionid。
@hinson0 谢谢你的回复。
-
express 内的session 机制 express-session 已处理掉,不是我的问题所在,并我已测试过如不用 微信扫回调机制session 是没有问题,并校对过req.sessionID是对的。
-
微信扫一扫回调事件之后我的req.sessionID 已发变化了。在图示就能看出。 问过 node-wechat api 的作者,其建议我用oauth。我就不明白是无法更正的问题还是存在的bug。
@mrlong 我现在的做法是,依然使用session,但是不使用express-session。将sessionid以login接口的值传入给前端,前端会在浏览器的Localstorage出保存起来。我之前也考虑oauth2。不过因为是自己做,oauth2相对而言,是一种“授权”,所以就还是使用session了。
帖段我的代码:
// 依赖
var moment = require('moment');
var async = require('async');
var uid = require('uid-safe').sync;
var redis = require('../library/redis').create();
// UserService
var UserService = {
setSession: function (user, req) {
var sid = uid(24);
var expired = moment().unix() + 7 * 24 * 60 * 60;
var session = {
id: sid,
expired: expired,
user: user.get({plain: true}),
user_id: user.id
};
var stringify = JSON.stringify(session);
redis.set(sid, stringify);
req.session = session;
req.user = user;
},
destroySession: function (req) {
redis.expire(req.session.id, 0);
},
checkSession: function (req, res, next) {
async.waterfall([
// get session id
function (cb) {
var sid = req.query.sid;
if (!sid) {
cb('请登录后访问');
} else {
cb(null, sid);
}
},
// get session
function (sid, cb) {
redis.get(sid, function (err, session) {
if (session) {
cb(null, session);
} else {
console.log('session empty, sid ' + sid);
cb('请登录后访问');
}
});
},
// check whether session expired or not
function (session, cb) {
var parsed = JSON.parse(session);
if (parsed.expired <= moment().unix()) {
console.log('session expired, sid ' + session.id);
cb('请重新登录后访问');
} else {
cb(null, parsed);
}
},
], function (err, session) {
if (err) {
res.status(403);
res.json({msg: err});
} else {
console.log('userid ' + session.user_id + ' session check success');
next();
}
});
},
isMe: function (req, userId) { // 是否为自己
var me = req.session.user_id;
return parseInt(me) === parseInt(userId);
}
};
module.exports = UserService;
setSession方法是在login出调用,destroySession是在logout出,而checkSession则是在需要校验session的接口处调用
@mrlong 因为通过微信的事件回调后,request cookie是无法跟着ajax一直走的,因此在回调的requestcookie中没有带入connect.sid,因此你的req.sessionid就是新的值。我也是因为这个问题,才换了一种思维,让前端在localstorage中存sessionid,而不是用cookie。
@hinson0 谢谢你及时回复。
-
从你的代码中我明白了,pc 采用扫一扫微信登录,是涉及到两个端 一个是pc浏览器,及微信端。 按原理 必然会生成两个不同的sessionID。
-
唯一的交点就是pc生成的二维码怎么与微信端扫后关联起来。 我查了node-wechat 的api 生成临时的qrcode 只有保存 场景id (int 型) 不是string , 无将sessionID 转到微信端。 '’’js /**
- 创建临时二维码
- 详细请看:http://mp.weixin.qq.com/wiki/index.php?title=生成带参数的二维码
- Examples:
-
- api.createTmpQRCode(10000, 1800, callback);
-
- Callback:
-
err
, 调用失败时得到的异常
-
result
, 调用正常时得到的对象
- Result:
-
- {
- "ticket":"gQG28DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0FuWC1DNmZuVEhvMVp4NDNMRnNRAAIEesLvUQMECAcAAA==",
- "expire_seconds":1800
- }
-
- @param {Number} sceneId 场景ID
- @param {Number} expire 过期时间,单位秒。最大不超过1800
- @param {Function} callback 回调函数 */ exports.createTmpQRCode = function (sceneId, expire, callback) { this.preRequest(this._createTmpQRCode, arguments); }; ‘’’