Используя Express и Node, как поддерживать сеанс в поддоменах / заголовках хоста - PullRequest
11 голосов
/ 31 января 2012

У меня есть сервер с одним узлом, который отвечает на запросы и перенаправляет пользователя на основе заголовков узлов.Использование заключается в том, что статический / домашний сайт находится на www, и у каждого пользователя есть свой собственный поддомен (т.е. www.example.com и site.example.com).Маршрутизация выполняется в соответствии с site.js.

Когда пользователь не вошел в систему, он перенаправлен на вход в систему.

Я обнаружил, что сеанс не поддерживается, когда пользователь перенаправляется на егоподдомен.Я предполагаю, что это ожидается, но мне интересно, есть ли способ поддерживать один и тот же сеанс в обоих поддоменах.

Я надеялся, что если они войдут в систему и вернутся на www.example.com, онисм. другое представление, включающее ссылку на выход из системы / их панель мониторинга и т. д. Я думаю, что на данный момент я могу обойтись, просто создав сеанс на своем поддомене, и если они вернутся на www, это будет так, как если бы онине вошли в систему.

Кто-нибудь имел дело с этим раньше или есть ответы о том, как обрабатывать сессии таким образом?

Я думаю, что проблема может быть в users.js, куда я перенаправляю на 'http://site.example.com' как не относительный путь ...

Вот соответствующий код (поиск пользователя выполняется с использованием MongoDB, и я оставил его в порядке своей работы - строка, которая вызывает этот сервис, является пользователями.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 в мой файл hosts, чтобы запросы DNS обрабатывались локально.

Ответы [ 3 ]

25 голосов
/ 31 января 2013

Прежде всего, чтобы браузер мог отправлять междоменные запросы, вам нужно установить заголовки на стороне сервера. Это решение работает как для обычного запроса, так и для 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();
});

Access-Control-Allow-Origin можно установить на «*», если междоменные файлы cookie не обмениваются на сеансы. Чтобы иметь cookie-файлы и сеанс общего междоменного домена, вам нужно установить конкретный Access-Control-Allow-Origin для фактического домена, из которого сделан запрос, поэтому req.headers.origin - идеально подходит для этого.

При использовании домена он не будет хорошо работать на локальном хосте - поэтому убедитесь, что вы отключили его в среде разработки и включили на производстве. Это позволит использовать общие файлы cookie в верхних и дополнительных доменах.

Это еще не все. Браузеры сами по себе не будут отправлять файлы cookie по запросам между доменами, и это необходимо принудительно. В jQuery вы можете добавить дополнительный параметр в запросе $ .ajax ():

xhrFields: { withCredentials: true }

Для не jQuery, просто используйте конструктор XHR и установите этот параметр:

xhr.withCredentials = true;

И вы готовы сделать кросс-домен с общим сеансом.

2 голосов
/ 31 января 2012

Вы удостоверились, что ваши куки настроены на домен верхнего уровня, чтобы он мог быть прочитан всеми поддоменами?Тогда это просто вопрос или сохранение ваших данных сеанса в памяти, дБ, как угодно.У меня не запущена и не запущена моя dev-машина, но она будет выглядеть примерно так в вашем app.configure ().

app.use(express.cookieParser());

app.use(express.session({  
  key: 'A_SESSION_KEY',   
  secret: 'SOMETHING_REALLY_HARD_TO_GUESS',   
  store: new express.session.MemoryStore,  
  cookie: {  
    path     : '/',  
    domain   : 'yourdomain.com',  
    httpOnly : true,  
    maxAge   : 1000*60*60*24*30*12    //one year(ish)  
  }   
}));
0 голосов
/ 07 мая 2014

Примечание. При использовании Express 4 и нового модуля cookie-сессии код выглядит как

{ 
  secret: <session_secret> , 
  store: <session store> , 
  domain: '.domain.com',
}

Это немного меня, но API изменился.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...