当前位置: 首页 > 面试题库 >

使用Express和Node,如何在子域/主机头之间维护会话

洪光霁
2023-03-14
问题内容

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

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

我发现当用户重定向到其子域时,无法维护该会话。我想这是预料之中的,但我想知道是否有一种方法可以在两个子域之间维持相同的会话。

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

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

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

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

server.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"

users.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。在您的快速配置功能中:

Express 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的原因-非常适合。

使用domain不能在localhost上正常工作-因此请确保在开发环境中将其禁用,并在生产环境中启用。它将启用跨顶级域和子域的共享cookie。

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

xhrFields: { withCredentials: true }

对于非jQuery,只需具有XHR构造函数并设置以下参数:

xhr.withCredentials = true;

您就可以使用共享会话进行跨域了。



 类似资料:
  • 问题内容: 此方法不正确。我试图找出的是一种不知道将存在哪些cookie,能够处理cookie更改以及维护会话的方法。 我正在为我的简单机器论坛编写一个应用程序,当您单击某些自定义行为时,它会更改其cookie配置。 但是,如果该应用程序对我的网站运行良好,我将发布一个供其他论坛使用的版本。 我知道我朝着正确的方向前进,但是逻辑有点像在踢我的屁股。 任何建议将不胜感激。 问题答案: 这段代码很混乱

  • 问题内容: 是否有使用节点,表达和redis / predis共享PHPSESSID的最新指南(或示例代码)? 我发现有1-2年的一些教程,它们都使用旧版本的Express或不使用Express。 Express cookie解析器也已弃用。 https://simplapi.wordpress.com/2012/04/13/php-and-node-js-session-share- redi/

  • 我正在寻找一个持久的会话管理器,将会话保存在文件系统(如PHP)上,可以与DropWizard一起使用。我看到有一个<code>环境。getSessionHandler(),但我没有看到关于它的文档。 我可以写我自己的,但我希望有一个煮熟的饭。上面的会话句柄是我要找的吗?如何使用它?

  • 我有两个问题。我理解,如果我在cookie中指定域为(带前导点),那么所有子域都可以共享一个cookie。 是否可以访问在中创建的cookie(没有子域)? 如果在中创建,(没有子域)是否可以访问cookie?

  • 如何在restasured中设置会话属性?在我的应用程序代码中,我们有如下内容 String userId = request.getSession().getAttribute(“userid”) 如何在此处将 userId 设置为会话属性(在重新保证的测试用例中)? 如何为所有请求(多个后续请求)维护同一会话? 当我发送多个请求时,它认为每个请求都是新的,会话从服务器端失效,我想在后续调用之间

  • 我正在尝试登录到一个网站,并获得一个页面站点的页面源后,我用java URLConnection登录到该网站。我面临的问题是我无法维护会话,所以服务器给我这个警告,不让我连接: 该系统要求使用HTTP Cookie来验证授权信息。我们的系统检测到您的浏览器已禁用HTTP Cookie,或不支持它们。有关如何正确配置浏览器以便与此系统一起使用的详细信息,请参阅浏览器中的帮助页。 这是我的源代码: