Empêcher Expressjs de créer une session lorsque les demandes contiennent un en-tête d’autorisation?

J’ai une API qui peut être appelée en utilisant un navigateur où les demandes sont transactionnelles et ont une session OU directement, par exemple. using curl, où les requêtes sont atomiques. Les requêtes du navigateur doivent d’abord s’authentifier, puis utiliser une session express (connect.sid) pour une autorisation ultérieure. Les appels d’API directs utilisent un en-tête: Authorization: "SOMETOKEN" qui doit être envoyé pour chaque requête.

Le problème que j’ai, c’est que, parce que j’utilise le même serveur Web pour gérer le trafic atomique et transactionnel, chaque appel d’API reçoit inutilement une session de Express. Chaque réponse inclut un Set-Cookie et toutes ces sessions remplissent mon magasin de sessions. Par conséquent: comment empêcher Express de saisir une nouvelle clé sess dans la mémoire (Redis) lorsqu’une demande contient un en-tête Authorization?

Remarque. Je comprends qu’une approche plus classique consisterait à disposer d’un serveur API et d’un serveur Web distincts, mais pourquoi ne pas exécuter les deux sur une seule machine? Pour moi, la différence est que l’API sert des données et le WEB sert des vues mais au-delà, ils font tous les deux partie de la même application. Il se trouve que j’autorise également les utilisateurs à accéder directement à leurs données et ne les force pas à utiliser mon interface.

Express Config

 module.exports = function(app, exp, sessionStore, cookieParser, passport, flash) { app.configure(function(){ // Templates app.set('views', ERNEST.root + '/server/views'); app.set('view engine', 'jade'); app.set('view options', { doctype : 'html', pretty : true }); // Allow large files to be uploaded (default limit is 100mb) app.use(exp.limit('1000mb')); // Faux putting and deleting app.use(exp.methodOverride()); // Static content app.use(exp.static(ERNEST.root + '/server')); app.use(exp.static(ERNEST.root + '/public')); // Handle favicon app.use(exp.favicon()); // For uploads app.use(exp.bodyParser({keepExtensions: true})); // Configure cookie parsing if ( cookieParser ) app.use(cookieParser); else app.use(exp.cookieParser()); // Where to store the session var session_options = { 'secret': "and she put them on the mantlepiece" }; if ( sessionStore ) session_options.store = sessionStore; app.use(exp.session( session_options )); // Rememberance app.use( function (req, res, next) { if ( req.method == 'POST' && req.url == '/authenticate' ) { if ( req.body.rememberme === 'on' ) { req.session.cookie.maxAge = 2592000000; // 30*24*60*60*1000 Rememeber 'me' for 30 days } else { req.session.cookie.expires = false; } } next(); }); // PassportJS if ( passport ){ app.use(flash()); app.use(passport.initialize()); app.use(passport.session()); } }); }; 

Un exemple d’itinéraire

 app.get('/status/past_week', MID.ensureAuthenticated, MID.markStart, function(req, res) { WEB.getStatus('week', function(err, statuses){ if ( err ) res.send(500, err); else res.send(200, statuses); }); }); 

Middleware d’autorisation

 MID.ensureAuthenticated = function(req, res, next) { if ( req.isAuthenticated() ) return next(); else { isAuthorised(req, function(err, authorised){ if ( err ) return res.redirect('/'); else if ( authorised ) return next(); else return res.redirect('/'); }); } function isAuthorised(req, callback){ var authHeader = req.headers.authorization; if ( authHeader ) { // Has header, verify it var unencoded = new Buffer(authHeader, 'base64').toSsortingng(); var formatted = unencoded.toSsortingng().sortingm(); ACCOUNT.verifyAuth(formatted, callback); // verifyAuth callbacks next() when successful } else callback(null, false); // No Authorised header } }; 

Essaye ça:

 var sessionMiddleware = exp.session( session_options ); app.use(function(req, res, next) { if (req.headers.authorization) { return next(); } return sessionMiddleware(req, res, next); }); 

On dirait que vous devez écrire votre propre middleware de session. Voici un exemple . Si vous pouvez créer un sous-domaine distinct, par exemple http://www.example.com pour les sessions de navigateur et app.example.com pour y accéder directement, vous devriez pouvoir utiliser la méthode liée de manière presque exacte et ne pas démarrer la session. pour les demandes app.example.com. C’est peut-être la méthode la plus directe par laquelle l’appel indique la méthode par laquelle il entend s’authentifier. Toute déviation de cette méthode est une erreur.

Sinon, vous devrez détecter le jeton d’authentification dans le middleware et ne pas démarrer la session quand vous le trouverez.

Une autre approche pour réduire le nombre de sessions stockées dans votre stockage de session consiste à définir un maxAge par défaut sur une valeur basse. Ensuite, lorsque vous avez réellement besoin de sessions stockées plus longtemps, comme après une connexion utilisateur, vous pouvez définir req.session.cookie.expires = null; . N’oubliez pas non plus de définir un délai d’expiration de session faible lorsque l’utilisateur se déconnecte.

Voici un exemple:

 // set default to something low app.use(session({ resave: true, saveUninitialized: true, cookie: { maxAge: 5 * 60 * 1000 // 5 minutes }, secret: secrets.sessionSecret, store: new MongoStore({ url: yourUrl, auto_reconnect: true }) })); // on successful login, // set expiration to null or something longer than default var time = 14 * 24 * 3600000; //2 weeks req.session.cookie.maxAge = time; req.session.cookie.expires = new Date(Date.now() + time); req.session.touch(); // on logout, reset expiration to something low var time = 5 * 60 * 1000; // 5 minutes req.session.cookie.maxAge = time; //2 weeks req.session.cookie.expires = new Date(Date.now() + time); req.session.touch(); 

Ceci est particulièrement utile lors de la surveillance à distance de votre application, car si la surveillance est suffisamment fréquente, les sessions se saturent rapidement.

Vous pouvez toujours simplement capturer l’événement d’en-tête de réponse et supprimer l’ 'set-cookie' tête 'set-cookie' :

 app.use(function(req, res, next) { res.on('header', function () { if (req.headers.authorization) { delete res._headers['set-cookie']; } }); next(); }); 

Vous pouvez techniquement mettre cela n’importe où dans votre chaîne de middleware.