使用 Express 和 Node,如何跨子域/主机头维护 Session

2024-02-28

我有一个单节点服务器,它响应请求并根据主机标头重定向用户。用法是静态/主站点位于 www,每个用户都有自己的子域(即 www.example.com 和 site.example.com)。路由按照 site.js 进行。

当用户未登录时,他们将被重定向到登录。

我发现当用户重定向到其子域时,会话不会维持。我想这是预期的,但我想知道是否有办法在两个子域之间维护相同的会话。

我希望,如果他们登录并返回 www.example.com,他们会看到一个不同的视图,其中包括注销/仪表板等的链接。我想,我目前的解决方法是创建他们的子域上的会话,如果他们返回 www,就好像他们没有登录一样。

有人以前处理过这个问题或者对如何以这种方式处理会话有答案吗?

我认为问题可能出在 users.js 中,我重定向到“http://site.example.com”,因为它不是相对路径...

这是相关的代码(用户查找是使用 MongoDB 完成的,我将其省略,因为它工作正常 - 调用此服务的行是 users.authenticate)...

服务器.js:

app.configure ->
app.set "views", "#{__dirname}/views"
app.set "view engine", "jade"
app.use express.bodyParser()
app.use express.methodOverride()
app.use express.cookieParser()
app.use express.session { 
    key: "KEY", 
    secret: "SECRET", 
    store: new MemoryStore(), 
    cookie: { 
        domain: 'example.com', 
        maxAge   : 1000*60*60*24*30*12 
    }
}
app.use express.static "#{__dirname}/public"
app.use express.logger "short"
app.use express.favicon "#{__dirname}/public/img/favicon.ico"
app.use app.router

site.js:

module.exports = (app) ->
app.get '/', (req, res) ->
    console.log "/ hit with #{req.url} from #{req.headers.host}"
    domains = req.headers.host.split "."
    org = if domains then domains[0] else "www"
    if org == "www"
        res.render "index", { layout: null }
    else
        if req.session.user
            console.log "session established"
            res.render "app", { layout: null }
        else
            console.log "no session"
            res.redirect "http://www.example.com/accounts/login"    

用户.js:

users = require('../services/users')
module.exports = (app) ->
app.get "/accounts/login", (req, res) ->
    res.render "login", { layout: null, locals: { returnUrl: req.query.returnUrl } }
app.post "/accounts", (req, res) ->
    users.authenticate app, req.body.login, req.body.password, (user) ->
        if user
            req.session.user = user
            res.redirect "http://#{user.orgName}.example.com"
        else
            res.render "login", { layout: null, locals: { returnUrl: req.body.url } }
app.get "/accounts/logout", (req, res) ->
    console.log "deleting user from session"
    delete req.session.user
    res.redirect "http://www.example.com                

为了在 OSX 上进行本地测试,我已将 www.example.com 和 site.example.com 添加到我的主机文件中,以便在本地处理 DNS 查找。


首先,为了允许浏览器发出跨域请求,您需要在服务器端设置标头。该解决方案适用于普通请求以及 AJAX。 在您的快速配置功能中:

快递4.0:

var express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');

var app = express();

app.use(cookieParser());
app.use(session({
    secret: 'yoursecret',
    cookie: {
        path: '/',
        domain: 'yourdomain.com',
        maxAge: 1000 * 60 * 24 // 24 hours
    }
}));
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');
    next();
});

如果不需要跨域 cookie 交换会话,则可以将 Access-Control-Allow-Origin 设置为“*”。 要跨域共享 cookie 和会话,您需要将特定的 Access-Control-Allow-Origin 设置为发出请求的实际域,这就是 req.headers.origin 非常适合的原因。

使用域它在本地主机上无法正常工作 - 因此请确保在开发环境中禁用它,并在生产环境中启用它。它将启用跨顶级域和子域的共享 cookie。

这还不是全部。 浏览器本身不会通过跨域请求发送 cookie,而这必须是强制的。 在 jQuery 中,您可以在 $.ajax() 请求中添加额外的参数:

xhrFields: { withCredentials: true }

对于非 jQuery,只需使用 XHR 构造函数并设置此参数:

xhr.withCredentials = true;

您已准备好通过共享会话进行跨域。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Express 和 Node,如何跨子域/主机头维护 Session 的相关文章

随机推荐