我已经将后端变成了API。而且API控制器具有HttpBasicAuth类型身份验证。
问题在于,即使在前端进行身份验证之后,只要向API发出请求,身份验证窗口就会出现。
我该怎么做,以便当用户在前端进行身份验证时,在向API发出请求时,不再要求用户访问密码和用户名?
API中的控制器示例:
class CategoryController extends ActiveController
{
public $modelClass = 'api\models\Category';
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'authMethods' => [
[
'class' => HttpBasicAuth::className(),
'auth' => function($username, $password) {
$out = null;
$user = \common\models\User::findByUsername($username);
if ($user != null) {
if ($user->validatePassword($password)) $out = $user;
}
return $out;
}
],
],
];
return $behaviors;
}
}
答案 0 :(得分:2)
这称为共享会话。这还取决于您的分层应用程序(前端和api)是否都在同一域中。如果是这样,请按照以下步骤配置前端和api设置(<app>/frontend/config/main.php
和<app>/api/config/main.php
):
'components' => [
...
'request' => [
'csrfParam' => '_csrf-shared',
],
...
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-shared', 'httpOnly' => true],
],
...
'session' => [
'name' => 'advanced-shared',
],
...
这意味着您以相同的名称保存cookie和会话,以便当您登录前端并转到backend / api时,后端将获取相同的cookie,因此您将被检测为经过身份验证的用户。
这里有一个重要说明,为了使enableAutoLogin
在两个级别上均有效,您应该为两个cookieValidationKey
设置相同的main-local.php
。您可以手动设置它们,或编辑init.php
文件为所有层生成一个cookieValidationKey。 (只需确保您知道自己在做什么)。
顺便说一句,我认为在frontend
和api
之间进行同时认证不是一个好主意。如果是frontend
和backend
,那么它仍然可以忍受,但是api
的交互作用与frontend
有所不同。
我建议使用诸如Authorization: Bearer <token>
之类的标题。您可以在Yii2 Rest Authentication
我认为这就是您所需要的。在ApiAuth
文件夹中创建一个类,即common/components
并粘贴以下代码:
<?php
namespace common\components;
use yii\filters\auth\HttpBasicAuth;
class ApiAuth extends HttpBasicAuth
{
/**
* @inheritdoc
*/
public function authenticate($user, $request, $response)
{
if ($user->identity) {
return $user->identity;
}
return parent::authenticate($user, $request, $response);
}
}
此类从yii\filters\auth\HttpBasicAuth
扩展。在调用浏览器提示之前,它会检查是否填充了user->dentity
。如果是这样,则不需要promt。
在Controller行为中,将HttpBasicAuth
替换为ApiAuth
类:
use common\components\ApiAuth;
...
'authMethods' => [
[
'class' => ApiAuth::className(),
'auth' => function($username, $password) {
...
答案 1 :(得分:0)
由于用户已经通过身份验证,因此我只需为连接的用户设置“ AccessControl”。如果他们没有连接,他们将收到代码403而不是401。
这可以解决问题:
class CategoryController extends ActiveController
{
public $modelClass = 'api\models\Category';
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['access'] = [
'class' => \yii\filters\AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['@'],
],
],
];
return $behaviors;
}
}