Passport js 无法跨域维护会话
Posted
技术标签:
【中文标题】Passport js 无法跨域维护会话【英文标题】:Passport js fails to maintain session in cross-domain 【发布时间】:2013-10-03 07:45:14 【问题描述】:我正在使用护照 JS、express 和 mongoose 来制作 API。当我在同一个域中测试它时,它会保持会话并且工作正常。但是在跨域中它失败了。任何线索我如何使用相同的配置在跨域中维护会话。以下是代码
allowCrossDomain = function(req, res, next)
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", req.headers["access-control-request-headers"]);
// res.header("Access-Control-Allow-Credentials", "true");
if ("OPTIONS" == req.method)
res.send(200);
else
next();
//allow all crossDomain request
app.use(allowCrossDomain);
//session handling
app.use(express.cookieParser("gallery"));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next)
// check if client sent cookie
var cookie = req.cookies.cokkieName;
if (cookie === undefined)
//set up cookie here by a random number
);
next(); // <-- important!
);
passport.use(new LocalStrategy(
usernameField: "email"
,
function(email, password, done)
User.authenticate(email, password, function(err, reply)
//authenticate user and call the callback
return done(err, false);
);
));
passport.serializeUser(function(user, done)
return done(null, user._id);
);
passport.deserializeUser(function(id, done)
//find user via id and return the user details
return done(null, user._id);
);
app.post("/login", function(req, res, next)
passport.authenticate("local",
function(err, data, info)
//custom callback
user.getProfile(req, res, next, err, data, info);
)(req, res, next);
);
【问题讨论】:
@kundu_ 你得到解决方案了吗? 【参考方案1】:我遇到了同样的问题。在快速应用中配置任何内容之前,请使用以下(完全相同)设置跨域响应的标头:
app.use(function(req, res, next)
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if ('OPTIONS' == req.method)
res.send(200);
else
next();
);
它对我有用。祝你好运!
【讨论】:
你知道为什么会这样吗?为什么需要凭据? 我也面临同样的问题,这个解决方案仍然不适合我。我该怎么办?请帮忙。 OP 应该接受这个答案。这真是天才,先生,你救了我的命。【参考方案2】:根据 Sriharsha 的回答:
设置res.header("Access-Control-Allow-Credentials", "true");
确保在客户端调用中传递凭据。例如对于 AJAX,将其添加到您的调用中:xhrFields: withCredentials: true,
另外:
不要将通配符用于带有凭据请求的 Access-Control-Allow-Origin
作为explained on MDN:
在响应凭据请求时,服务器必须指定一个 域,并且不能使用通配符
我使用这个文件,并从我的主模块中调用它require("./enable-cors.js")(app);
// enable-cors.js
module.exports = function(app)
var methodOverride = require('method-override')
app.use(methodOverride());
var allowCrossDomain = function(req, res, next)
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// intercept OPTIONS method
if ('OPTIONS' == req.method)
res.send(200);
else
next();
;
app.use(allowCrossDomain);
// Built upon: http://cuppster.com/2012/04/10/cors-middleware-for-node-js-and-express/#sthash.WdJmNaRA.dpuf
;
【讨论】:
【参考方案3】:通过设置 Access-Control-Allow-Credentials 标头允许共享凭据。 (我不知道你为什么在你的代码中评论)
res.header("Access-Control-Allow-Credentials", "true");
然后 pass the credentials 从 javascript 通过 XHR 对象。
xhr.withCredentials = true;
【讨论】:
以上是关于Passport js 无法跨域维护会话的主要内容,如果未能解决你的问题,请参考以下文章
Nodejs + Passport.js + Redis:如何在 Redis 中存储会话