Tạo một phần mềm trung gian expressjs chấp nhận các tham số


104

Tôi đang cố gắng tạo một phần mềm trung gian có thể chấp nhận các tham số. Điều này có thể giải quyết như thế nào?

thí dụ

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

})

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

   next();
}

41
Ha, bạn đã hỏi câu hỏi chính xác của tôi cho kịch bản chính xác của tôi, nhưng 6 năm trước đó. Thật là tuyệt vời.
hàng không

6
@aero chính xác thứ mà tôi đang tìm kiếm: D
Jeson Dias

4
@aero 7 năm sau, tôi đang tìm một chính xác như nhau: D
Jean d'Máy trộn

4
@aero hơn 7 năm sau, tôi đang tìm kiếm điều tương tự!
sidd

4
@aero 8 ~ năm sau, tôi đang tìm kiếm điều tương tự! \ o /
Ítalo Sousa

Câu trả lời:


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

Tôi cũng muốn đảm bảo rằng tôi không tạo nhiều bản sao của cùng một hàm:

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

9
Phương thức thứ hai lưu trữ các tham số, hoặc có thể không phải là hành vi mong muốn.
Pier-Luc Gendreau

1
@Jonathan Ong, bạn có thể vui lòng giải thích định nghĩa thứ hai của hàm được không. Điều gì đang xảy ra ở đó? Tôi không hiểu dòng sau trả về HasRole [role] || (HasRole [role] = function (req, res, next) {
Rafay Hassan

1
@JonathanOng, bạn có thể vui lòng giải thích ví dụ thứ hai thêm một chút cho những người không biết nút tốt không? (bao gồm cả tôi). Khi nào bạn có thể nhận được nhiều bản sao của cùng một chức năng và khi nào điều này có thể gây ra sự cố? Cảm ơn.
Dave

mà không có bộ nhớ đệm app.get('/a', hasRole('admin'))app.get('/b', hasRole('admin'))sẽ tạo một đóng mới cho mỗi hasRole. Điều này thực tế không quá quan trọng trừ khi bạn có một ứng dụng thực sự lớn. tôi chỉ viết mã như thế này theo mặc định.
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();
};

Ý tưởng hay và đơn giản. Middleware thực sự chỉ là một chức năng bình thường. Tại sao không chuyển các giá trị khác cho nó. Vui lòng bao gồm req, res và next trong hàm đầu tiên.
zevero

1
Mặc dù mã thường tự nói lên điều đó, nhưng thật tốt khi thêm một số giải thích vào mã của bạn. Điều này xuất hiện trong hàng đợi xem xét, vì các câu trả lời chỉ có mã có xu hướng.
Will

Tôi đã nghĩ về cách tiếp cận đó trước khi truy cập SO, nhưng tôi nghĩ "Meh, chắc chắn có một cách tốt hơn". Sau khi tham quan, tôi thấy rằng đây thực sự là cách đơn giản nhất, hiệu quả nhất.
Fusseldieb

3

Ngoài ra, nếu bạn không có quá nhiều trường hợp hoặc nếu vai trò KHÔNG phải là một chuỗi:

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

})

giải pháp thanh lịch
Leos Literak

2

Nếu bạn có các mức quyền khác nhau, bạn có thể cấu trúc chúng như sau:

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

Tôi sử dụng giải pháp này. Tôi nhận được mã thông báo jwt trong yêu cầu nội dung và nhận thông tin vai trò từ đó

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

Vì vậy, trước tiên tôi sử dụng phần mềm trung gian auth để biết liệu có phải là người dùng hợp lệ hay không và sau đó là phần mềm trung gian vai trò để biết liệu người dùng có quyền truy cập vào tuyến api hay không

// router.js

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

Tôi hy vọng sẽ hữu ích

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.