2016-12-20 6 views
0

angular-fullstackを使用してWebアプリケーションを構築しています。スタックは、セッションストレージ(Mongodbの場合)にはexpress-sessions、認証にはpassport.jsを使用しています。Passportミドルウェア、ライブセッションが既にあるかどうかを確認してください

各ユーザーを1回のログインセッションに制限したいと考えています。私は、ログインしたユーザーがすでにライブセッションを持っているかどうかを確認する方法を見つけようとしています。

パスポートミドルウェアからmongodbを照会するルートをプログラムで呼び出す方法はありますか?

'use strict'; 

import path from 'path'; 

import passport from 'passport'; 
import {Strategy as LocalStrategy} from 'passport-local'; 

import express from 'express'; 
import session from 'express-session'; 

import _ from 'lodash'; 
import Session from '../../api/session/session.model'; 

var app = express(); 
require('run-middleware')(app); 

function localAuthenticate(User, email, password, done, req) { 
    User.findOne({ 
    email: email.toLowerCase() 
    }).exec() 
    .then(user => { 

     if (!user) { 
     return done(null, false, { 
      message: 'This email is not registered.' 
     }); 
     } 

     // HERE is where I am trying to check if a user 
     // already has a living session when they login 

     // I tried to use the runMiddleware 
     // to query mongodb for all the existing sessions 
     // but I get this error: http://pastebin.com/YTeu5AwA 
     app.runMiddleware('/sessions',{},function(code,data){ 
     console.log(code) // 200 
     console.log(data) // { user: '20', name: 'Moyshale' } 
     }); 

     // Is there a way to access and use an existing route? 

     user.authenticate(password, function(authError, authenticated) { 
     if (authError) { 
      return done(authError); 
     } 
     if (!authenticated) { 
      return done(null, false, { message: 'This password is not correct.' }); 
     } else { 
      return done(null, user); 
     } 
     }); 
    }) 
    .catch(err => done(err)); 
} 

export function setup(User, config) { 

    passport.use(new LocalStrategy({ 
    passReqToCallback: true, 
    usernameField: 'email', 
    passwordField: 'password' // this is the virtual field on the model 
    }, function(req, email, password, done) { 
    return localAuthenticate(User, email, password, done, req); 
    })); 
} 
+0

[この質問](http://stackoverflow.com/questions/21434922/node-js-one-session-per-user)とその答えを確認してください。 – robertklep

答えて

0

わかりました。私はそれを理解して、私がしたことを説明しようとします。私の具体的な実装では、各ユーザがグループの一部であり、各グループがN回のログインで一度に制限されるユーザの座席を設定する必要がありました。

enter image description here

私は質問で述べたように、私は角fullstackヨーマン・ジェネレータを使用していますので、このソリューションは、その設定に固有のものです。

  1. 私はモンゴDBに保存されたセッションを照会し、修正することができるように、私は「セッション」API endpointを作成しました。セッションモデルにNumber型の '座席'レコードを追加しました。これは、各セッションのユーザーのシート状態を追跡するために使用されます。各ユーザには、このフィールドに値を設定するために使用される 'loginSeat'値が与えられます。また、セッションにはBoolean型のseatAllowedがあります。つまり、ユーザーはサイトにアクセスできます。false:ユーザーはサイトへのアクセスを許可されていません。

    'use strict'; 
    
    import mongoose from 'mongoose'; 
    
    var SessionSchema = new mongoose.Schema({ 
        _id: String, 
        session: String, 
        expires: Date, 
        seat: Number, 
        seatAllowed: Boolean // true: the user is allowed to access the site, false: the user is not allowed access to the site 
    }); 
    
    export default mongoose.model('Session', SessionSchema); 
    
  2. 時にユーザがログインするサイトに、マッチング座と他のすべてのユーザーが出てぶつかっているように、私はserver/auth/login/passport.jsを変更しました。

    'use strict'; 
    
    import path from 'path'; 
    
    import passport from 'passport'; 
    import {Strategy as LocalStrategy} from 'passport-local'; 
    import _ from 'lodash'; 
    import Sessions from '../../api/session/session.model'; 
    
    function saveUpdates(updates) { 
        return function(entity) { 
        var updated = _.merge(entity, updates); 
        return updated.save() 
         .then(updated => { 
         return updated; 
         }); 
        }; 
    } 
    
    function localAuthenticate(User, email, password, done, req) { 
        User.findOne({ 
        email: email.toLowerCase() 
        }).exec() 
        .then(user => { 
         if (!user) { 
         return done(null, false, { 
          message: 'This email is not registered.' 
         }); 
         } 
    
         // When a user logs into the site we flag their seat as allowed 
         var updateSession = {'seat': user.loginSeat, 'seatAllowed': true}; 
    
         Sessions.findById(req.session.id).exec() 
         .then(saveUpdates(updateSession)) 
    
         // When a user logs into the site, we disallow the seats of all other sessions with matching seat 
         Sessions.find().exec() 
         .then(sessions => { 
    
         // Check for existing user logged in with matching login seat 
         for (var i = 0; i < sessions.length; i++) { 
          if (sessions[i].seat === user.loginSeat && sessions[i].id !== req.session.id) { 
          console.log('DISALOW SEAT:'); 
          var updateSession = {'seatAllowed': false}; 
    
          Sessions.findById(sessions[i].id).exec() 
           .then(saveUpdates(updateSession)); 
          } 
         } 
         }); 
    
         user.authenticate(password, function(authError, authenticated) { 
         if (authError) { 
          return done(authError); 
         } 
         if (!authenticated) { 
          return done(null, false, { message: 'This password is not correct.' }); 
         } else { 
          return done(null, user); 
         } 
         }); 
        }) 
        .catch(err => done(err)); 
    } 
    
    export function setup(User, config) { 
    
        passport.use(new LocalStrategy({ 
        passReqToCallback: true, 
        usernameField: 'email', 
        passwordField: 'password' // this is the virtual field on the model 
        }, function(req, email, password, done) { 
        return localAuthenticate(User, email, password, done, req); 
        })); 
    } 
    
  3. クライアントがisAuthenticated機能がトリガーされた要求をするたびに。それ

    function saveUpdates(updates) { 
        return function(entity) { 
        var updated = _.merge(entity, updates); 
        return updated.save() 
         .then(updated => { 
         return updated; 
         }); 
        }; 
    } 
    
    /** 
    * Attaches the user object to the request if authenticated 
    * Otherwise returns 403 
    */ 
    export function isAuthenticated() { 
    
        return compose() 
        // Validate jwt 
        .use(function(req, res, next) { 
    
         // Allow access_token to be passed through query parameter as well 
         if (req.query && req.query.hasOwnProperty('access_token')) { 
         req.headers.authorization = 'Bearer ' + req.query.access_token; 
         } 
         validateJwt(req, res, next); 
    
        }) 
        // Attach user to request 
        .use(function(req, res, next) { 
    
         User.findById(req.user._id).exec() 
         .then(user => { 
          if (!user) { 
          return res.status(401).end(); 
          } 
          req.user = user; 
    
          /////////////////////////// 
          // Login seat limitation // 
          /////////////////////////// 
    
          // Check if the user seat is allowed 
          Sessions.findById(req.session.id).exec() 
          .then(thisSession => { 
           // TODO access the session in a better way 
           if (thisSession.seatAllowed === false || thisSession.seatAllowed === undefined) { 
           res.redirect('/login'); 
           } 
          }) 
          next(); 
         }) 
         .catch(err => next(err)); 
        }); 
    } 
    

厥:私はそれ以外のユーザーをログアウトする、真の場合、現在のセッションのseaAllowedブールをチェックし、ユーザーがサイトにアクセスできるようにする場所です。

関連する問題