Erstellen einer ExpressJS-Middleware, die Parameter akzeptiert


94

Ich versuche eine Middleware zu erstellen, die Parameter akzeptieren kann. Wie kann das gemacht werden?

Beispiel

app.get('/hasToBeAdmin', HasRole('Admin'), function(req,res){

})

HasRole = function(role, req, res, next){
   if(role != user.role){
      res.redirect('/NotInRole);
   }

   next();
}

38
Ha, Sie haben meine genaue Frage für mein genaues Szenario gestellt, aber 6 Jahre zuvor. SO ist großartig.
Aero

6
@ Aero genau das, wonach ich gesucht habe: D
Jeson Dias

4
@aero 7 Jahre später suche ich genau das gleiche: D
Jean d'arme

4
@aero 7+ Jahre später suche ich genau das Gleiche!
Sidd

4
@aero 8 ~ Jahre später suche ich genau das Gleiche! \ o /
alotalo Sousa

Antworten:


153
function HasRole(role) {
  return function(req, res, next) {
    if (role !== req.user.role) res.redirect(...);
    else next();
  }
}

Ich möchte auch sicherstellen, dass ich nicht mehrere Kopien derselben Funktion erstelle:

function HasRole(role) {
  return HasRole[role] || (HasRole[role] = function(req, res, next) {
    if (role !== req.user.role) res.redirect(...);
    else next();
  })
}

9
Die zweite Methode speichert Parameter zwischen, die das gewünschte Verhalten sein können oder nicht.
Pier-Luc Gendreau

1
@ Jonathan Ong, können Sie bitte die zweite Definition der Funktion erklären. Was passiert da? Ich verstehe die folgende Zeile nicht. Geben Sie HasRole [Rolle] || zurück (HasRole [Rolle] = Funktion (req, res, next) {
Rafay Hassan

1
@JonathanOng Könnten Sie bitte das zweite Beispiel etwas näher erläutern, wenn Sie den Knoten nicht so gut kennen? (mich eingeschlossen). Wann können Sie mehrere Kopien derselben Funktion erhalten und wann kann dies zu Problemen führen? Vielen Dank.
Dave

ohne Zwischenspeichern app.get('/a', hasRole('admin'))und app.get('/b', hasRole('admin'))würde für jeden einen neuen Abschluss erstellen hasRole. Dies ist realistisch gesehen nicht allzu wichtig, es sei denn, Sie haben eine wirklich große Anwendung. Ich codiere nur standardmäßig so.
Jonathan Ong

14
app.get('/hasToBeAdmin', (req, res, next) => {
  hasRole(req, res, next, 'admin');
}, (req,res) => { 
    // regular route 
});

const hasRole = (req, res, next, role) => {
   if(role != user.role){
      res.redirect('/NotInRole');
   }
   next();
};

Gute und einfache Idee. Middleware ist wirklich nur eine normale Funktion. Warum nicht andere Werte übergeben? Bitte geben Sie req, res und next in die erste Funktion ein.
Zevero

1
Während Code oft für sich selbst spricht, ist es gut, Ihrem Code eine Erklärung hinzuzufügen. Dies tauchte in der Überprüfungswarteschlange auf, da nur Code-Antworten dazu neigen.
Will

Ich habe über diesen Ansatz nachgedacht, bevor ich SO besucht habe, aber ich dachte "Meh, es gibt sicherlich einen besseren Weg". Nach dem Besuch sehe ich, dass dies wirklich der einfachste und effektivste Weg ist.
Fusseldieb

3

Alternativ, wenn Sie nicht zu viele Fälle haben oder wenn die Rolle KEINE Zeichenfolge ist:

function HasRole(role) {
  return function (req, res, next) {
    if (role !== req.user.role) res.redirect(/* ... */);
    else next();
  }
}

var middlware_hasRoleAdmin = HasRole('admin'); // define router only once

app.get('/hasToBeAdmin', middlware_hasRoleAdmin, function (req, res) {

})

elegante Lösung
Leos Literak

2

Wenn Sie über verschiedene Berechtigungsstufen verfügen, können Sie diese folgendermaßen strukturieren:

const LEVELS = Object.freeze({
  basic: 1,
  pro: 2,
  admin: 3
});

/**
 *  Check if user has the required permission level
 */
module.exports = (role) => {
  return (req, res, next) => {
    if (LEVELS[req.user.role] < LEVELS[role]) return res.status(401).end();
    return next();
  }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.