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();
}
Vartan Arabyan
quelle
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();
  })
}
Jonathan Ong
quelle
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();
};
chovy
quelle
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) {

})
Zevero
quelle
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();
  }
}
asdf
quelle