web-dev-qa-db-ja.com

ExpressとNodeを使用して、サブドメイン/ホストヘッダー間でセッションを維持する方法

リクエストに応答し、ホストヘッダーに基づいてユーザーをリダイレクトする単一ノードサーバーがあります。使用法は、静的/ホームサイトがwwwにあり、各ユーザーが独自のサブドメイン(つまり、www.example.comとsite.example.com)を持っていることです。ルーティングはsite.jsによるものです。

ユーザーがログインしていない場合、ユーザーはログインにリダイレクトされます。

ユーザーがサブドメインにリダイレクトされたときにセッションが維持されないことがわかりました。これは予想されることだと思いますが、両方のサブドメインで同じセッションを維持する方法があるかどうか疑問に思っています。

ログインしてwww.example.comに戻ると、ログアウトやダッシュボードなどへのリンクを含む別のビューが表示されることを期待していました。現時点での回避策は、作成することだけだと思います。サブドメインでのセッション。wwwに戻った場合は、ログインしていないかのようになります。

誰かが以前にこれに対処したか、この方法でセッションを処理する方法についての答えがありますか?

問題は、相対パスではないため、「http://site.example.com」にリダイレクトするusers.jsにあると思います...

関連するコードは次のとおりです(ユーザールックアップは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をhostsファイルに追加して、DNSルックアップがローカルで処理されるようにしました。

16
mattgi

まず、ブラウザがクロスドメインリクエストを実行できるようにするには、サーバー側でヘッダーを設定する必要があります。このソリューションは、AJAXだけでなく通常のリクエストでも機能します。エクスプレス設定機能の場合:

Express 4.

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;

そして、共有セッションでクロスドメインを実行する準備が整いました。

28
moka

すべてのサブドメインで読み取れるように、Cookieがトップレベルドメインに設定されていることを確認しましたか?次に、通常どおり、セッションデータをメモリやデータベースに保持するだけです。開発マシンを稼働させていませんが、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)  
  }   
}));
2
daviddripps

注:Express 4と新しいCookieセッションモジュールを使用している場合、コードは次のようになります。

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

これは私を苦しめましたが、APIが変更されました。

1
Kevin Boyle