2016-12-20 3 views
0

Ich baue eine Webanwendung mit angular-fullstack. Der Stack verwendet express-sessions für Sitzungsspeicher (in Mongodb) und pass.js zur Authentifizierung.Passport Middleware, überprüfen Sie, ob der Benutzer bereits eine lebendige Sitzung hat von

Ich möchte jeden Benutzer auf eine einzige Login-Sitzung beschränken. Ich versuche einen Weg zu finden, zu überprüfen, ob ein Benutzer bereits eine Live-Sitzung hat, wenn er sich anmeldet.

Gibt es eine Möglichkeit, programmatisch eine Route aufzurufen, um mongodb von der Pass-Middleware abzufragen?

'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

Überprüfen Sie [diese Frage] (http://stackoverflow.com/questions/21434922/node-js-one-session-per-user) und ihre Antwort. – robertklep

Antwort

0

Ok, ich es herausgefunden und ich werde versuchen und erklären, was ich tat. Bei meiner spezifischen Implementierung musste ich Usersitze einrichten, bei denen jeder Benutzer Teil einer Gruppe ist und jede Gruppe in einer einzigen Anzahl von N Logins begrenzt ist.

enter image description here

Wie ich in der Frage erwähnt, ich bin mit dem Winkel fullstack Yeoman Generator, so dass diese Lösung ist spezifisch für diese Einrichtung.

  1. Ich habe eine ‚Sitzungen‘ API endpoint so, dass ich die Sitzungen in der Mongo DB gespeichert abfragen könnte und ändern. Ich habe einen 'Sitz' Datensatz mit dem Typ Nummer in das Sitzungsmodell aufgenommen. Dies wird verwendet, um den Sitzstatus des Benutzers für jede Sitzung zu verfolgen. Jeder Benutzer erhält einen "loginSeat" -Wert, mit dem dieses Feld ausgefüllt wird. Außerdem hat die Sitzung jetzt einen SitzplatzAllowed vom Typ Boolean, true: Der Benutzer darf auf die Site zugreifen, false: Der Benutzer hat keinen Zugriff auf die Site.

    '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. I modifiziert server/auth/login/passport.js so dass, wenn sich ein Benutzer an der Stelle, alle anderen Benutzer mit einem passenden Sitz gestoßen werden wird.

    '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. Jedes Mal, wenn der Client eine Anfrage ausgelöst wird, die isAuthenticated Funktion macht. Dies ist, wo ich für die seaAllowed boolean für die aktuelle Sitzung überprüfen, wenn sie wahr sind, ermöglichen es dem Benutzer auf die Website zugreifen, sonst abzumelden den Benutzer:

    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)); 
        }); 
    } 
    

Thats it.

Verwandte Themen