매개 변수를 받아들이는 expressjs 미들웨어 만들기


107

매개 변수를 받아 들일 수있는 미들웨어를 만들려고합니다. 어떻게 할 수 있습니까?

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

})

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

   next();
}

42
하, 당신은 내 정확한 시나리오에 대해 정확한 질문을했지만 6 년 전에. 그래서 굉장합니다.
aero

6
@aero 내가 찾던 것과 똑같은 것 : D
Jeson Dias

4
@aero 7 년 후 나는 똑같은 똑같은 것을 찾고 있어요 : D
jean d' arme

4
@aero 7 년 이상 후 나는 똑같은 것을 찾고 있습니다!
sidd

4
@aero 8 ~ 년 후 똑같은 것을 찾고 있어요! \ o /
Ítalo Sousa

답변:


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

또한 동일한 기능의 복사본을 여러 개 만들지 않았는지 확인하고 싶습니다.

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

9
두 번째 방법은 원하는 동작이거나 아닐 수있는 매개 변수를 캐시합니다.
Pier-Luc Gendreau

1
@Jonathan Ong, 함수의 두 번째 정의를 설명해 주시겠습니까? 거기에서 무슨 일이 일어나고 있습니까? 다음 줄을 이해하지 못합니다 return HasRole [role] || (HasRole [역할 = 함수 (REQ, 입술 옆) {
Rafay 산

1
@JonathanOng 노드를 잘 모르는 사람들을 위해 두 번째 예제를 조금 더 설명해 주시겠습니까? (나를 포함해서). 동일한 기능의 여러 사본을 언제 얻을 수 있으며 언제 문제가 발생할 수 있습니까? 감사.
Dave

캐싱없이, app.get('/a', hasRole('admin'))그리고 app.get('/b', hasRole('admin'))각각의 새로운 클로저를 만들 것입니다 hasRole. 정말 큰 응용 프로그램이 없다면 이것은 현실적으로 그다지 중요하지 않습니다. 나는 기본적으로 이렇게 코딩합니다.
조나단 옹

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

좋고 간단한 아이디어. 미들웨어는 실제로 정상적인 기능입니다. 다른 값을 전달하지 않는 이유는 무엇입니까? 첫 번째 기능에 req, res 및 next를 포함하십시오.
zevero

1
코드는 종종 그 자체로 말하지만 코드에 설명을 추가하는 것이 좋습니다. 이것은 코드 전용 답변이 경향이 있기 때문에 리뷰 대기열에 나타납니다.

그래서 방문하기 전에 그런 접근 방식을 생각하고 있었는데 "메, 확실히 더 좋은 방법이있다"고 생각했습니다. 방문 후 나는 이것이 정말로 가장 간단하고 효과적인 방법이라는 것을 알았습니다.
Fusseldieb

3

또는 케이스가 너무 많지 않거나 역할이 문자열이 아닌 경우 :

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

})

우아한 솔루션
Leos Literak

2

다양한 권한 수준이있는 경우 다음과 같이 구성 할 수 있습니다.

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

이 솔루션을 사용합니다. body req에서 jwt 토큰을 받고 거기에서 역할 정보를 얻습니다.

//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 }

그래서 먼저 인증 미들웨어를 사용하여 유효한 사용자인지 확인한 다음 역할 미들웨어를 사용하여 사용자가 api 경로에 액세스 할 수 있는지 확인합니다.

// router.js

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

도움이 되길 바랍니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.