Authentication 認證
RESTful Api
是無狀態的, 因此這意味着不能使用 sessions && cookies
。
因此每一個請求應該帶有一些 authentication credentials
因為用戶的 authentication
狀態可能不是保存在 sessions || cookies
中的。
一個通用的實例就是在發送每一個請求的同時帶一個 secret access token
來驗證用戶。因為一個 access token
可以用來確定一個唯一的用戶和驗證這個用戶, API Requests
應該總是通過 https
協議來傳輸, 以防止 man-in-the-middle (MitM)
攻擊。
有多種不同的方式來發送 access token
:
HTTP Basic Auth
access token
作為一個用戶名被傳遞。這種情況只適合“當access token
可以安全的存儲在API 接收端”的情況, 比如 調用 API 的是一個在服務器上運行的程序
- Query parameter
access token
在 API URL 中作為一個查詢參數被傳遞,比如https://example.com/users?access-token=123456789
- 因為多數的 Web 服務器會保存 query 參數在服務器日志中, 這個方法應該主要是用於響應無法使用 HTTP 頭部信息來發送
access token
的JSONP
請求的。
- OAuth 2
- 遵照
OAth2.0
協議, 調用者從一個授權服務器
上獲取access token
, 再通過HTTP Bearer Tokens
發送給Api 服務器
。
- 遵照
Yii 支持上面的幾種認證方式, 你也可以自己創建新的認證方法。
要對你的 APIs
啟用認證的話, 遵照下面的步驟:
- 配置
user
組件的yii\web\User::enableSession|enableSession
屬性為false
- 在你的 REST 控制器中 指明你准備使用哪一種
authenticator
方法 - 在你的
yii\web\User::identityClass|user identity class
中實施yii\web\IdentityInterface::findIdentityByAccessToken()
第一步並不是必須, 但是針對無狀態的 RESTful APIs 還是建議要有。 當 yii\web\User::enableSession|enableSession
是 false
的時候, 用戶認證狀態不能通過 sessions
在多個請求之間保持。反倒是, 第二步和第三部的配置會對來的每一個請求都執行認證檢查。
Tips: 你可以在應用的 configurations 的 user application component 中配置
yii\web\User::enableSession|enableSession
, 如果你是將 RESTful APIs 作為一個 模塊 module, 你可以像下面一樣在 module的 init() 方法中添加代碼:
public function init()
{
parent::init();
\Yii::$app->user->enableSession = false;
}
下面針對上面幾種情況,在 Yii2
的情況下舉幾個例子:
第一種情況, 使用 HTTP Basci Auth
use yii\helpers\ArrayHelper;
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return ArrayHelper::merge(
parent::behaviors(),[
'authenticator' => [
'class' => HttpBasicAuth::className(),
]
]
);
}
如果你想要使用上面講到的 3 種方式, 可以像下面一樣使用 CompositeAuth
:
use yii\helpers\ArrayHelper;
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasciAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
#這個地方使用`ComopositeAuth` 混合認證
'class' => CompositeAuth::className(),
#`authMethods` 中的每一個元素都應該是 一種 認證方式的類或者一個 配置數組
'authMethods' => [
HttpBasicAuth::className(),
HttpBearerAuth::className(),
QueryParamAuth::className(),
]
]
]);
}
例如, 一個簡單的情景是當每一個用戶只能擁有一個 ·access token· 的時候, 你可以在 user
表中的 access_token
列存儲它。這種方式可以像下面一樣輕易的實現:
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function findIndentityByAccessToken($token)
{
return static::findOne(['access_token' => $token]);
}
}
經過上面的認證之后, 對每一個 API 請求, 被請求的 控制都會 在它的 beforeAction()
步驟之前嘗試認證用戶。
如果認證成功, 控制器會執行其他的檢查,(比如rate limiting, authorization)。被認證了的用戶的認證信息可以通過 Yii::$app->user->identity
獲得。
如果認證失敗, 一個 401 HTTP 狀態的響應會被發送回來連同其他的頭部信息 (比如一個 HTTP BASIC Auth 認證的 WWW-Authenticate
頭部信息)
Authorization 授權
一個用戶經過認證
之后, 你可能還想要檢查他是否有對請求的資源執行某個請求動作的權限。這個過程叫做授權
授權是驗證用戶是否有足夠權限做一些事情的過程。(譯者注:Authentication就是驗證是否注冊,Authorization是檢查已登錄用戶是否有權限) Yii 提供了兩種方法來管理授權:
訪問控制過濾器(Access Control Filter,簡稱 ACF)和 基於角色的訪問控制(Role-Based Access Control,簡稱 RBAC)。
如果你的控制器 extend yii\rest\ActiveController
, 你可以覆蓋重寫 yii\rest\Controller::checkAccess()|checkAccess()
方法來執行授權檢查。因為這個方法會被內建動作 yii\rest\ActiveController
調用。