yii2-restful的全局认证和局部认证的接口设置

时间:2022-10-05 10:07:52
yii2在使用restful作为接口的时候,yii\rest\Controller中已经把全局的csrf验证设置为false,

public $enableCsrfValidation = false;

也就是在post数据的时候,不会在进行_csrf参数的验证。

那么在开发restful接口的时候,比如一个app的服务端restful接口,用户分为游客和登录用户,一开始,游客打开这个app的时候,他并没有登录,只是游客身份来访问,那么这时候,app的页面必须的有内容显示,这些内容就是通过restful接口返回的json数据。

所以这些不需要token认证的restful接口就必须设置可以直接访问内容,无需认证,当然这也就是权限设置。

当一个游客点击app的一个tag,例如“我”,那么对于关于“我”的这个接口,在服务端肯定是要判断用户是否登录了,这个接口只有登录用户才能使用,所以就需要进行token的认证。

总的来说,也就是一些restful接口请求的内容呢,公共开放的内容不管是什么身份,只要访问了都可以有权限访问,不需认证。而对于一些属于私人的内容呢,就必须要登录了,通过认证了才能访问。

在yii2的restful中,我们可以设置三种安全认证的方式,参考:
http://www.yiichina.com/doc/guide/2.0/rest-authentication

第一种情况, 使用 HTTP Basci Auth

use yii\helpers\ArrayHelper;
use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
$parent = parent::behaviors();

$parent['authenticator'] => [
'class' => HttpBasicAuth::className(),

/**
如果设置了这个auth,就会按照这个auth进行认证,可以查看yii\filters\auth\HttpBasicAuth源码,
如果没设置这个属性,那么就会使用access-tokend的方式实现,$username作为access-token,
使用main.php配置中的User组件类实现,而且User组件类类中必须设置loginByAccessToken()函数实现。
所以,如果使用HttpBasicAuth的话,强烈建议设置auth属性
*/
'auth' => function ($username, $password) {
return \app\models\User::findOne([
'username' => $username,
'password' => $password,
]);
}
]
}


第二种情况是access-token的方式

use yii\helpers\ArrayHelper;
use yii\filters\auth\QueryParamAuth;

public function behaviors()
{
$parent = parent::behaviors();

$parent['authenticator'] => [
'class' => QueryParamAuth::className(),
// 设置token名称,默认是access-token
'tokenParam' => 'token'
]
}


下面看一下yii\filters\auth\QueryParamAuth的authenticate()

public function authenticate($user, $request, $response)
{
$accessToken = $request->get($this->tokenParam);
if (is_string($accessToken)) {
$identity = $user->loginByAccessToken($accessToken, get_class($this));
if ($identity !== null) {
return $identity;
}
}
if ($accessToken !== null) {
$this->handleFailure($response);
}

return null;
}

当我们请求的时候,将会获取到这个$accessToken = $request->get($this->tokenParam)的值。

然后调用$user->loginByAccessToken()这个组件的loginByAccessToken()去进行验证,$user也就是我们在配置文件中配置的认证的User组件,对应的class,在这里我设置的是api\models\User,也就是这个User类必须实现loginByAccessToken()这个函数,函数里面具体的业务自己定义了。

第三种方式就不说了。

当在一个restful的控制器中的

public function behaviors()  {

}

设置了以上的认证方式,那么就会开启整个认证,也就是访问这个控制器的每一个请求的action都会进行验证,也就是全局验证。

所以,根据上面说的一些业务,我们知道有一些内容,是任意用户都可以看的,不需要登录,不需要认证的,但现在问题是只要设置了认证方式,不管哪个restful接口请求都要认证,也就是全局认证,那怎么办?

对此,我们就必须能够在behaviors()进行一些设置,比如定义一些需要登录和认证的才能访问的函数action有哪些,然后与当前访问的操作action进行比较即可。

 function behaviors() {
$behaviors = parent::behaviors();

// 当前操作的id
$currentAction = Yii::$app->controller->action->id;

// 需要进行认证的action
$authActions = ['index'];

// 需要进行认证的action就要设置安全认证类
if(in_array($currentAction, $authActions)) {

$behaviors['authenticator'] = [
'class' => QueryParamAuth::className(),
];
}
return ArrayHelper::merge([
//设置可以接收访问的域和方法。
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['*'],
// 'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['Origin', 'X-Requested-With', 'Content-Type', 'Accept'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
],
],
], $behaviors);

}

就是按照以上的设置就可以,将你觉得需要认证的action放在$authActions的数组里即可。当请求的是这些设置需要认证的action的时候,就会返回401,代表没办法认证通过,需要认证。