2017-10-18 6 views
0

私は議論のすべてを読みましたが、まだ理解できません。 Passport Js Webサイトのドキュメントは非常に曖昧です。Passport js serializeUser&deserializeUser

私はpassport-ldapauth戦略でPassport JSを使用しています。 私はデータベースを持っていません。 私は明らかに、それぞれのリクエストでLDAPサーバにヒットしたくありません。私は初めてLDAPを使ってパスポート戦略を使用してPOST /loginルートでユーザーを認証し、そのユーザーをセッションに保存して、その後の各要求に対してユーザーが既にログインしているかどうかを確認したいと考えています。

セッションを使用しようとしていますが、シリアライズ/デシリアライズフローでPassport +セッションを使用する方法を理解できません。 私がチェックしたすべての例では、deserializeUser関数でUser.findOneを使用しました。

今のところ私はPassportのセッションの使用を無効にしました。私はreq.session.user != nullをチェックするカスタムミドルウェアを使用しています。その場合、ユーザーは既にログインしていて、私はnext()になります。それ以外の場合は、ログインにリダイレクトします。

ここ

は、いくつかのコード(簡略化のために、私が質問に関連していないコードを削除した)である:

パスポート構成

var express = require('express'), 
    session = require('express-session'), 
    passport = require('passport'), 
    LdapStrategy = require('passport-ldapauth'); 

var app = express(); 

var LdapStrategyOptions = { 
    server: { 
    url: '<url>', 
    bindDN: '<dn>', 
    bindCredentials: "<pwd>", 
    searchBase: '<searchBase>', 
    searchFilter: '<filter>' 
    } 
}; 
passport.use(new LdapStrategy(LdapStrategyOptions)); 

app.use(cookieParser()); 
app.use(session({ 
    store: new LokiStore({autosave: false}), 
    resave: false, 
    saveUninitialized: false 
    secret: env.get("SESSION_SECRET") 
})); 

app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })); 

app.use(passport.initialize()); 

ルート

// LOGIN ROUTE 
app.get('/login', 
    function(req, res) { 
    res.render('login'); 
}); 

// LOGIN HANDLER ROUTE 
app.post('/login', 
    passport.authenticate('ldapauth', { session: false }), 
    function(req, res) { 
    req.session.userId = req.user.cn; 
    req.session.user = { 
     "userId": req.user.cn, 
     "displayName": req.user.displayName 
    }; 
    res.redirect('/'); 
}); 

// LOGOUT ROUTE 
app.get('/logout', 
    function(req, res) { 
    req.session.destroy(function(err) { 
     req.logout(); 
     res.redirect('/'); 
    }); 
}); 

// HOME ROUTE 
app.get('/', isLoggedIn, function(req, res) { 
    res.render('home'); 
}); 

IsLoggedInミドルウェア

var isLoggedIn = function(req, res, next) { 
    if (req.session.user != null){ 
    console.log("is auth ok '" + req.session.user.userId +"'"); 
    return next(); 
    } 

    console.log("redirect to auth/login"); 
    res.redirect('/auth/login'); 
} 

私は何が欠けていますか?セットアップにセキュリティ上の欠陥はありますか? 何か助けていただければ幸いです。

+0

'app.use(passport.session());'が不足している可能性がありますか? –

+0

番号。私が書いたように、私はpassport.deserializeUser()で何を書かなければならないのか理解できないので、サンプルコードから削除しました。 サンプルセッションは、カスタムセッション管理で動作させる方法と同じです。 – Roberto

答えて

0

passportjsドキュメントから:一般的なWebアプリケーションで

、ユーザーを認証するために使用される資格情報は、ログイン要求時に送信されます。認証が成功すると、セッションは確立され、ユーザのブラウザに設定されたクッキーを介して維持されます。

以降の要求には、資格情報は含まれず、セッションを識別する固有のCookieが含まれます。ログイン・セッションをサポートするために、Passportはセッションとの間でユーザー・インスタンスを直列化および非直列化します。基本的にはserializeUser

は後で戻ってJSONにdeserializeUserことができるようにユニークなユーザー識別子を返すことになっています。

免責事項:

は、だからあなたの実装のために、あなたはおそらく、これらの線に沿って何かを行う必要があり、私はLDAPとの経験がありません。

passport.serializeUser(function(user, done) { 
    //We can identify the user uniquely by the CN, 
    //so we only serialize this into the session token. 
    done(null, user.cn); 
}); 

passport.deserializeUser(function(cn, done) { 
    //Directly query LDAP. 
    //I'm not sure passport caches the result (only calls deserializeUser for new sessions) 
    //but worst case you can cache the result yourself. 
    somehowLoadUserFromLDAPByCN(cn, function(err, user) { 
    done(err, { 
    userId: user.cn, 
    displayName: user.displayName 
    }); 
    }); 
}); 
+0

Exaclty!しかし問題は、すべての要求に対してLDAP(リソース集中型プロセス)を使用したくないということです。同じことがデータベースにも当てはまります。要求ごとにDBのクエリを作成する必要があるのはなぜですか?それは私がパスポートの枠組みで理解していないものです。 – Roberto

+0

パスポートがこの機能の結果のキャッシングを処理するかどうかは思い出せません。ブレークポイントを設定し、すでに認証されているときに呼び出されているかどうかを確認することで、自分自身を確認できます。私の前提はそうではありません(パスポートはこれらの結果をキャッシュしたいのかどうか分からないので、この関数で自分自身をキャッシュすることができます。キャッシュの実装はあなた次第です(メモリ内、redisなど)。 –

+0

すでにリクエストされていても、すべてのリクエストに対してdeserializeUserが呼び出されます。私はまだこの機能の目的を得ることができません。なぜ地球上でリクエストごとに認証システム(DB、LDAP、Facebookサービス)を打つべきですか?セッションを使用してユーザー名、電子メール、およびそれらのものを格納できる場合、なぜ私はDBにユーザープロファイルをキャッシュする必要がありますか? – Roberto

1

IDと表示名だけが必要な場合は、セッション中のままにしても問題ありません。フィールドがさらに必要な場合にのみ、完全なユーザープロファイルを読み込む必要があります。

関連する問題