2012-02-22 61 views
21

在express.js中基於角色的授權有什麼好策略?特別是使用快遞資源?node.js和express.js中基於組/規則的授權方法

隨着Express-resource沒有處理,所以我覺得有三個選項:

  1. 使用中間件
  2. 傳遞的授權功能,資源和檢查每個資源請求分別與
  3. 檢查授權每個請求在認證後立即

是否有任何其他解決方案?

集團/基於角色的授權是一個非常古老的方法。有更新的訪問控制方法嗎?如果不是,基於角色的授權如何應用於node.js?何處存儲組規則關係(使用NoSQL/CouchDB/Redis)?

舉個例子,結構:

/ 
    /forums 
    /forums/threads 

與指數,新,創建,顯示,編輯更新和銷燬每個資源。有些人可以編輯/刪除等線程和論壇,有些人不應該。

回答

11

Connect-roles是相當不錯的,簡單的文檔也很清晰。

var user = roles; 

app.get('/profile/:id', user.can('edit profile'), function (req, res) { 
    req.render('profile-edit', { id: req.params.id }); 
}) 
app.get('/admin', user.is('admin'), function (req, res) { 
    res.render('admin'); 
} 
3

在表達式中,您可以添加一個處理程序,該程序可以掛接到每個運算符(http://expressjs.com/guide.html#passing-route控件)中,您可以在其中執行預處理驗證。在這裏,您可以檢索用戶的角色,並根據HTTP動詞(PUT,DELETE等)或URL(param('op')爲'edit'左右)限制訪問。

app.all('/user/:id/:op?', function(req, res, next){ 
    req.user = users[req.params.id]; 
    if (req.user) { 
    next(); 
    } else { 
    next(new Error('cannot find user ' + req.params.id)); 
    } 
}); 
+0

不幸的是,如上所述,這不適用於快遞資源。 – Patrick 2012-02-22 12:50:59

32

我要說的是,這是很難使用快車資源清潔的方式來解決這個問題,因爲它不允許路由專用中間件(至少不是在一個乾淨的方式)。

我會選擇一個類似於快速資源模塊的佈局,但可以用普通的舊快車進行佈局。事情是這樣的:

// Resource 
var forum = { 
    index: // ... 
    show: // ... 
    create: // ... 
    update: // ... 
    destroy: // ... 
}; 

// Middleware 
var requireRole = function(role) { 
    return function(req, res, next) { 
    if('user' in req.session && req.session.user.role === role) 
     next(); 
    else 
     res.send(403); 
    } 
}; 

// Routing 
app.get('/forums', forum.index); 
app.get('/forums/:id', forum.show); 
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums 
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums 

UPDATE:已經有關於快遞資源,例如路由專用中間件正在進行的討論here。普遍的觀點似乎是有動作每一個陣列,例如:

var forums = { 
    index: [ requireRole('foo'), function(req, res, next) { ... } ] 
}; 

你可以採取通過引入請求看看,看看是否有什麼你可以使用。當然,如果你對此感到不舒服,我完全理解它。我很確定我們將來會在快遞資源中看到類似的情況。

唯一的其他解決方案,我能想到的是沿揚Jongboom的答案的線,這將是安裝有明確的資源的資源,但有中間件連接的是「外」,是這樣的:

app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything 
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums 

但我很遺憾,這泄漏了所有地方的URL。

+0

問題是,有相當數量的資源,並且對於快速資源來說相當乾淨。我正在考慮一個可以與app.use()一起使用的小模塊,但我不知道如何編寫它。 – Patrick 2012-02-28 13:17:47

+0

帕特里克,我完全同意。請參閱上面的更新以獲得更多討論。除了我提到的關於此的更多的請求請求。我對此一無所知,但我有一種感覺,即3.0之後,TJ將更多地用於快遞資源,快遞名稱空間和公司,似乎有不少變化。 – 2012-02-28 14:03:55

2

我寫了一個模塊作爲非顯式路由中間件。適用於快速路線。

Gandalf on GitHub

+0

感謝@Patrick的中間件。有沒有一個很好的例子來說明如何在expressjs中使用它。我很抱歉,如果它聽起來像一個noobs問題,我對nodejs和表達很新。 示例將非常感謝 – praneybehl 2013-11-14 01:46:25

+0

@praneybehl我建議使用connect-roles或Linus的方法。甘道夫中間件已經過時。 – Patrick 2013-11-15 16:58:58

26

我一直在研究相同的問題,並遇到了一些很好的模塊。我一直關注可在此處找到的node-acl軟件包。 https://github.com/optimalbits/node_acl

這個軟件包似乎已經以一種非常容易理解的方式實現了ACL模式,並提供了將它輕鬆集成到您的節點/快速應用程序中的方法。

首先,您需要定義您的資源,角色和權限。

例如,資源可以是:

/ 
    /forums 
    /forums/threads 

角色可以是

public 
admin 
user 
    john 
    jane 

在這個例子中,角色約翰和簡可以映射到實際的用戶帳戶,但他們將繼承用戶角色的所有權限。

上的資源的權限

  • 創建
  • 顯示
  • 更新
  • 破壞

或者您的標準CRUD操作。

既然已經定義了那些,我們可以看看如何使用node-acl設置acl。這些說明從文檔

進口包裝

var acl = require('acl'); 

設置你的後臺導出。我的應用程序使用MongoDB的,但該節點的ACL包不支持其他存儲機制

acl = new acl(new acl.mongodbBackend(dbInstance, prefix)); 

我的應用程序是用貓鼬這樣dbinstance具備將與mongoose.connection.db更換

現在讓我們添加角色ACL。在node-acl中,通過給予角色權限來創建角色。它像二鳥一石(沒有鳥實際上是傷害)

acl.allow('admin', ['/', '/forum', '/forum/threads'], '*'); 
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show'); 
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']); 

讓我們假設一個新的資源是由約翰創建,我們將添加一個新的記錄,讓約翰還更新和刪除該資源。

acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']); 

我的應用程序也使用express,所以我將使用路由中間件的方法來檢查路由。在我的路由配置,我想補充的線

在大多數快遞配置,這就像是爲POS

app.post('/', acl.middleware(), function(req, res, next) {...}); 
app.post('/forums', acl.middleware(), function(req, res, next) {...}); 
app.post('/forums/:forumId', acl.middleware(), function(req, res, next) {...}); 
app.post('/forums/threads', acl.middleware(), function(req, res, next) {...}); 
app.post('/forums/threads/:threadId', acl.middleware(), function(req, res, next) {...}); 

當沒有參數傳遞,這將檢查是否在req.userId定義的角色允許對所標識的資源執行http方法,但執行路由。

在這個例子中,http方法是post方式,但是它會爲您在配置中識別的每個http執行相同的操作。

這引發了關於前面定義的權限的問題。要回答這些問題,我們必須從

  • 更改權限創建
  • 顯示
  • 更新
  • 破壞

傳統

  • 獲得
  • 刪除

雖然這個例子說明一切硬編碼的,更好的做法是讓你的權限的管理界面,使他們能夠創建,讀取,更新,動態刪除,而不修改你的代碼。

我喜歡node-acl插件的方法,因爲它允許使用非常直接和靈活的api進行非常細微的權限 - 角色分配。他們的文檔中有很多,我的示例演示是我使用這個軟件包。

希望這會有所幫助。

+0

什麼是公開的?我很難讓公共資源不受保護 – danielad 2016-09-29 11:29:49