Parametreleri kabul eden bir expressjs ara yazılımı oluşturma


106

Parametreleri kabul edebilen bir ara yazılım oluşturmaya çalışıyorum. Bu nasıl yapılabilir?

misal

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

})

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

   next();
}

42
Ha, benim tam senaryom için tam sorumu sordun, ama 6 yıl önce. SO harika.
aero

6
@aero tam olarak aradığım şey: D
Jeson Dias

4
@aero 7 yıl sonra aynısını arıyorum: D
jean d'arme

4
@aero 7+ yıl sonra aynı şeyi arıyorum!
2019

4
@aero 8 ~ yıl sonra aynı şeyi arıyorum! \ o /
Ítalo Sousa

Yanıtlar:


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

Aynı işlevin birden çok kopyasını yapmadığımdan da emin olmak istiyorum:

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

9
İkinci yöntem, istenen davranış olan veya olmayan parametreleri önbelleğe alır.
Pier-Luc Gendreau

1
@Jonathan Ong, lütfen fonksiyonun ikinci tanımını açıklar mısınız? Orada neler oluyor? Aşağıdaki satırı anlamıyorum dönüş HasRole [role] || (HasRole [role] = function (req, res, next) {
Rafay Hassan

1
@JonathanOng, düğümü o kadar iyi bilmeyenler için ikinci örneği biraz daha açıklar mısınız? (Ben dahil). Aynı işlevin birden çok kopyasını ne zaman alabilirsiniz ve bu ne zaman sorunlara neden olabilir? Teşekkürler.
Dave

önbelleğe almadan app.get('/a', hasRole('admin'))ve app.get('/b', hasRole('admin'))her biri için yeni bir kapanış oluşturacaktır hasRole. Gerçekten büyük bir uygulamanız olmadıkça bunun gerçekçi bir önemi yoktur. ben sadece varsayılan olarak böyle kodluyorum.
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();
};

İyi ve basit fikir. Middleware gerçekten normal bir işlevdir. Neden ona başka değerler geçmiyor? Lütfen ilk işlevde req, res ve next'i ekleyin.
zevero

1
Kod genellikle kendi adına konuşsa da, kodunuza bazı açıklamalar eklemek iyidir. Bu, yalnızca kod yanıtlarının eğiliminde olduğu için inceleme kuyruğunda belirdi.
Will

SO'yu ziyaret etmeden önce bu yaklaşımı düşünüyordum ama "Elbette daha iyi bir yolu var" diye düşündüm. Ziyaret ettikten sonra bunun gerçekten en basit ve en etkili yol olduğunu görüyorum.
Fusseldieb

3

Alternatif olarak, çok fazla vakanız yoksa veya rol bir dize DEĞİLSE:

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) {

})

zarif çözüm
Leos Literak

2

Çeşitli izin seviyelerine sahipseniz, bunları şu şekilde yapılandırabilirsiniz:

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

0

Bu çözümü kullanıyorum. Vücut isteğinde bir jwt jetonu alıyorum ve oradan rol bilgileri alıyorum

//roleMiddleware.js

const checkRole = role => {
    
    return (req, res, next) => {
        if (req.role == role) {
            console.log(`${role} role granted`)
            next()
        } else {
            res.status(401).send({ result: 'error', message: `No ${role} permission granted` })
        }
    }
}

module.exports = { checkRole }

Bu nedenle, önce geçerli bir kullanıcı olup olmadığını öğrenmek için kimlik doğrulama ara yazılımını ve ardından kullanıcının api yoluna erişimi olup olmadığını bilmek için rol ara yazılımını kullanıyorum.

// router.js

router.post('/v1/something-protected', requireAuth, checkRole('commercial'), (req, res) => {
    // do what you want...
})

Yararlı olmayı umuyorum

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.