天天看點

一個關于實作授權(Authorization)的完整指南

作者:IT分享站

什麼是授權?

授權是允許一個實體通路某物或在計算機系統中執行特定行動的過程。

在一個多使用者系統中,系統管理者使用授權機制來定義每個使用者或使用者組的權限。一旦一個使用者通過一個叫做認證的過程登入,系統就會決定在他們的會話中哪些資源應該被使用。是以,授權這個詞可以有兩個相關的含義。

  • 由系統管理者向使用者配置設定權限
  • 在運作時根據預先确定的權限向使用者授予通路權

認證與授權

認證是驗證使用者身份的過程,確定他們是他們所說的人。傳統上,最常見的身份認證方法是密碼。如果使用者提供的使用者名與密碼憑證相符,則身份被确定為有效,使用者被授予通路權。

密碼仍然被廣泛使用,但它們很容易被破壞,并且被廣泛認為是一種無效的安全機制。各組織正在向無密碼認證過渡,這對使用者來說更安全,也更友善。它依賴于多因素認證(MFA)、一次性密碼(OTPs)、電子郵件驗證和單點登入(SSO)等元素。

在使用者的身份通過認證得到驗證後,授權就開始發揮作用。它提供對資源的全部或部分通路,如裝置、檔案、應用程式、特定操作或資料。舉個簡單的例子。

  • 一個使用者登入到一個商業應用程式,提供他們公司的使用者名和密碼。
  • 應用程式對使用者進行認證,并驗證密碼。
  • 應用程式檢查配置設定給該使用者名的權限,并授予對相關資料和功能的通路權。

認證和授權對于安全來說都是至關重要的。通過實施強大的認證和強大的授權政策,一個組織確定它知道誰在通路其系統,以及他們到底能通路什麼。這可以提高使用者的生産力,同時保護敏感資産,滿足組織的安全和合規要求。

使用者授權政策和技術

  • 基于角色的通路控制(RBAC)

RBAC機制根據使用者在組織内的角色允許或限制他們的通路。它為使用者提供執行工作所需的資料和應用程式的通路權,同時最大限度地減少未經授權活動的風險,如通路敏感資料。

組織可以使用RBAC來定義每個使用者如何與資料互動。例如,它讓你允許特定角色的讀/寫或隻讀通路,以限制使用者執行未經授權的行動,如資料删除和指令執行。

企業使用基于角色的通路控制,根據員工的角色和職責定義的細化通路級别提供特權。這種方法有助于保護敏感資料,確定員工隻能通路其工作所需的資訊,并隻執行執行其任務所需的行動。

企業通常為每個員工配置設定一個基于角色的通路控制角色。這個角色為使用者定義了一系列的權限。你可以建立諸如管理者、專家和終端使用者等角色,限制每個角色對某些任務和資源的通路。

  • 基于屬性的通路控制(ABAC)

ABAC讓你根據屬性(或特征)而不是角色來定義通路和權限。它有助于保護網絡裝置、IT資源和資料等對象免受未經授權的行動和不具備組織的安全政策所定義的準許特征的使用者的影響。

ABAC從簡單的通路控制清單演變為一種邏輯通路控制的形式。它最初在2011年被聯邦首席資訊官委員會認可,以幫助聯邦組織改善通路控制架構。該委員會推薦ABAC以幫助組織安全地共享資訊。

  • 基于關系的通路控制(ReBAC)。

ReBAC根據使用者、應用程式和裝置等主體之間的關系來應用通路決策。當一個主體請求通路一個資源時,ReBAC機制根據該主體的關系授予或拒絕通路。

ReBAC不允許根據某種角色(如RBAC)或屬性(如ABAC)進行通路。相反,它是根據一個主體與其他實體的關系來允許通路。這些關系影響着授權政策如何授予或拒絕對受保護資源的通路。

社交網絡使用ReBAC來允許通路。例如,Facebook允許朋友的朋友通路照片和文章。這意味着朋友可以看到使用者的文章,也可以看到這些朋友的朋友。然而,這就是它的限制--第三方連接配接不允許通路。

  • JSON網絡令牌(JWT)

JSON網絡令牌(JWT)是一個開放标準,定義了如何在各方之間安全地傳輸資訊,如JSON對象。它通過數字簽名來驗證資訊。JWTs是緊湊的,自成一體的。你可以通過RSA或ECDSA使用公鑰/私鑰對來簽署JWT,或者通過HMAC算法使用秘密。

你也可以對JWT進行加密以提高安全性。簽名的令牌可以驗證票據的完整性,而加密的令牌可以隐藏票據,不被其他方發現。當你使用公鑰/私鑰對來簽署令牌時,簽名證明隻有持有私鑰的一方簽署了它。

你可以使用JWT進行授權機制。在使用者登入後,每個後續請求都包括JWT,以允許使用者通路這個令牌允許的服務、資源和路線。由于JWT可以很容易地用于不同的領域,而且開銷很小,是以它也為許多單點登入(SSO)機制提供動力。

  • 應用程式授權架構

Django授權

Django為快速開發和簡潔設計提供了一個Python網絡架構。Django認證包括認證和授權。由于這些功能在某種程度上是耦合的,是以這個機制可以作為一個認證系統。

下面是Django認證的核心元件。

  • 使用者-這些對象作為認證系統的基礎,通常代表與網站互動的人。你可以使用對象來限制通路,注冊使用者資料,并将内容與建立者聯系起來。
  • authenticate()-你可以使用這個元件來驗證一組憑證。它将憑證作為關鍵字參數、密碼和預設情況下的使用者名,并根據每個認證後端檢查它們。最後,如果憑證對後端有效,它傳回一個使用者對象。

Django包含一個内置的權限系統,可以讓你為特定的使用者以及使用者組配置設定權限。

ASP.NET授權

ASP.NET Core是一個開源架構,你可以用它來建構支援雲的網際網路連接配接的應用程式。它為現代的、跨平台的設計提供了高性能。

ASP.NET Core将授權定義為一個簡單的、聲明性的角色,由一個基于政策的模型執行。它讓你在需求中表達授權,而處理程式則根據這些需求評估每個使用者的要求。你可以将強制性檢查建立在簡單的政策或評估使用者身份和請求資源屬性的政策上。

Laravel授權

Laravel是一個開源的架構,為建構現代PHP應用程式提供了工具和資源。它提供了内置的認證服務和一個簡單的機制來授權使用者對每個資源的操作。這意味着一個使用者可以被認證,但沒有授權删除或更新特定的Eloquent模型或應用程式管理的資料庫記錄。

Laravel提供了兩個授權動作。

  • 閘門--采用一個簡單的, 基于封閉的授權方法.對于與特定的資源或模型無關的行動是理想的, 例如檢視管理者的儀表闆.
  • 政策--圍繞一個特定的資源或模型的邏輯分組。是授權特定模型或資源的行動的理想選擇。

沒有必要在閘門和政策之間進行選擇--你可以将這兩種選項混合在一起。

Spring授權

Spring是一個開源架構,為Java應用程式提供基礎設施支援。你可以用它來建立具有普通Java對象(POJO)的高性能應用程式。Spring Security提供了授權、認證和對常見網絡攻擊的保護。它可以幫助你保護必要的以及反應式的應用程式。

Spring Security提供了先進的授權功能,與各種機制配合使用。你可以使用Spring Security提供的機制或與非Spring Security認證機構內建,同時在你的應用程式中簡單而一緻地使用授權服務。

Node.js的授權

Node.js不提供内置的授權,但你可以用現成的庫為你的應用程式添加授權。

在Node.js中實作授權有很多方法--讓我們看看如何利用MySQL資料庫和bcryptjs密碼散列庫來實作。

重要提示:下面的代碼樣本包括代碼中的原始SQL查詢。這顯然不是一個好的做法,在任何時候都應該避免。但為了這些授權例子,我們用它們來示範功能。

第1步:建立路由檔案夾

在你的項目檔案夾中,建立一個名為rouse的子檔案夾,其中有兩個檔案。

  • routes/auth.js - 這個檔案應該使用router.post()函數定義兩個路由,一個用于注冊,例如在路徑/register,另一個用于登入,例如/login。
  • routes/index.js - 應該從 auth.js 檔案中導入路由,并定義哪個應用路徑應該被映射到這些路由 - 例如,/api/users。

第二步:實作注冊

建立一個控制器來注冊一個新的使用者 - 這個控制器應該建立一個使用者對象,包含使用者名、密碼和狀态等字段,并将其儲存到資料庫中。當接收到使用者的密碼時,使用bcrypt庫來安全地哈希它,像這樣。

const salt = await bcrypt.genSalt(10);

const hasPassword = await bcrypt.hash(req.body.password, salt);

建立一個模型檔案,将使用者的資料儲存到資料庫,像這樣。

User.create = async (newUser) => {

let insert = await sql.query("INSERT INTO user SET ?", newUser);

if( insert.insertId ) {

return insert.insertId;

}

else {

return;

}

};

第3步:實施登入

建立一個控制器,檢查使用者是否存在,然後建立一個JSON Web Token(JWT)。

const token = jwt.sign({id: user.id, user_type_id: user.user_type_id}, config.TOKEN_SECRET);

res.header("auth-token", token).send({"token": token});

使用bcrypt來比較使用者提供的憑證和密碼的散列版本,像這樣。

const validPass = await bcrypt.compare(req.body.password, user.password);

建立一個模型,安全地從資料庫中讀取使用者的詳細資訊。

User.login = async (value) => {

let row = await sql.query(`SELECT * FROM user WHERE mobile = ? OR email = ?`, [value, value]);

if( row.length ) {

return row[0];

}

else {

throw new NotFoundError("User does not exist");

}

};

第4步:添加認證和授權

要添加一個簡單的使用者認證和授權機制,你可以在請求的頭中檢查一個JSON網絡令牌(JWT),然後相應地允許或拒絕該請求。

警告。這是一個簡化的實作,用于學習目的,不适合用于生産應用。

這段代碼檢查JWT的字段user_type_id,它可以是1代表管理者,也可以是2代表普通使用者。

如果沒有标記,應用程式會傳回 "拒絕通路"。

exports.loggedIn = function (req, res, next) {

let token = req.header('Authorization');

if (!token) return res.status(401).send("Access Denied");

否則,我們檢查user_type_id的值。

try {

if (token.startsWith('Bearer ')) {

token = token.slice(7, token.length).trimLeft();

}

const verified = jwt.verify(token, config.TOKEN_SECRET);

if( verified.user_type_id === 2 ){

//If the user is not an admin, we check authorization for the requested URL:

let req_url = req.baseUrl+req.route.path;

if(req_url.includes("users/:id") && parseInt(req.params.id) !== verified.id){

return res.status(401).send("Unauthorized!");

}

}

req.user = verified;

next();

}

catch (err) {

res.status(400).send("Invalid Token");

}

}

這個功能會自動拒絕普通使用者對任何定義為僅供管理的路線的通路。

exports.adminOnly = async function (req, res, next) {

if( req.user.user_type_id === 2 ){

return res.status(401).send("Access Denied");

}

next();

}

授權的最佳實踐

  • 在軟體開發生命周期的早期設計和實施授權

授權功能是一個重要的安全元件,應該在軟體開發生命周期的早期階段考慮。在建構應用程式時考慮到安全問題,有助于確定設計本身的安全性,在産品已經準備好釋出時減少複雜和昂貴的修複。在設計授權時,要考慮所有關于角色和權限的要求,并使用支援這種授權類型的最合适的網絡架構。

  • 實施授權中間件

授權中間件使你能夠配置短暫的授權授予,并設定伺服器對每個請求進行連續的授權。這意味着授權中間件處理請求,消除了與API端點和未受保護的URL路徑相關的風險。

  • 實施授權政策

授權政策使你能夠配置和執行細粒度的通路控制。你可以使用各種類型的政策,如強制通路控制(MAC)、RBAC、ABAC或酌情通路控制(DAC)。

根據OWASP基金會的說法,ABAC比RBAC更可取。然而,你應該選擇适合應用要求的方法,在某些情況下,ABAC可能不是最佳選擇。理想情況下,授權類型應該至少包括一個強制性的 "預設拒絕 "政策,以阻止未經授權的通路。

  • 實施範圍界線

範圍界線為功能和特性定義了一個爆炸半徑。它可以減少那些設法繞過安全控制的威脅的影響。将功能和特性限制在一個特定的範圍内可以幫助避免各種漏洞,如本地檔案包含(LFI)、遠端檔案包含(RFI)和目錄周遊。你可以通過允許列出特定的本地目錄、程式二進制檔案和URL端點來實作範圍限制。

  • 驗證和淨化動态值

驗證過程包括資料驗證,而淨化過程試圖清理惡意輸入。對所有計算授權的值(包括使用者輸入)進行适當的淨化和驗證,可以幫助防止對許多漏洞的利用。以下是關鍵的最佳實踐:

  • 驗證和淨化必須包括使用者輸入和計算授權所需的所有會話資料。
  • 輸入的淨化和驗證必須在伺服器端進行。

使用有範圍限制的輸入驗證和淨化可以幫助你避免與參數篡改和漏洞有關的安全風險,如路徑周遊、RFI和LFI。

  • 在内部應用中實施認證和SSO

應用程式應始終包括通路控制。你可以使用Oauth2、SAML或OpenID Connect等标準來實作單點登入(SSO)。SSO是一種認證方案,使你能夠将認證和授權政策管理推遲到外部身份提供者。SSO被認為是應用安全的一個标準,但你可以使用其他認證方法。

繼續閱讀