Yii2中最简单的基础认证——IdentityInterface的实现

The most simple basic authentication in Yii2 - implementation of IdentityInterface

我想将 HTTP 基本身份验证添加到我的 Yii2 应用程序中,其中 username/password 存储在 Yii 配置文件中 - 对于一个用户,没有数据库身份验证。

我通过添加 behaviors 功能为我的控制器启用了身份验证:

public function behaviors()
    {
        return [
            'basicAuth' => [
                'class' => \yii\filters\auth\HttpBasicAuth::className(),
                'auth' => function ($username, $password) {
                    if ($username=='api') {
                        return new SimpleApiUser();
                    } else {
                        return null;
                    }
                },
            ],
        ];
    }

我需要创建 class,它实现了 IdentityInterface,这就是为什么我有 class:

class SimpleApiUser implements IdentityInterface {

    public static function findIdentity($id)
    {
        return null;
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return null;
    }

    public function getId()
    {
        return 1;
    }

    public function getAuthKey()
    {
        return 1;
    }

    public function validateAuthKey($authKey)
    {
        return true;
    }
}

很好,应用程序在第一个请求的情况下要求 username/password,但随后它设法以某种方式将身份验证存储在某个内部会话中,并且不需要为每个新请求重复身份验证它是由浏览器(我的添加会话)生成的,还是由 Postman 生成的(当然不会保留会话)。是否可以修改用户 class 以要求为每个新请求提供用户名和密码?

我试过使用您的代码。

首先,您的代码足以要求基本身份验证成为每个请求的一部分。如果 Authorization header 在请求中不存在,yii 将 return 401 Unauthorized。所以您的实施已经在做您需要的事情了。

用户不必每次都输入username/password是有原因的。

对于网络浏览器: 为 session 保存凭据,浏览器将在每个后续请求中自动发送它们,而无需用户再次提示。

对于邮递员:只要您不手动删除授权设置,就会为请求存储授权,它将作为每个请求的一部分发送。

如果你想强制用户在每个请求中手动输入 username/password 你可以扩展 HttpBasicAuth 组件来假装授权不是像这样的每个其他请求的请求的一部分

use Yii;
use yii\filters\auth\HttpBasicAuth;

class MyHttpBasicAuth extends HttpBasicAuth
{
    const SESSION_KEY = 'authForced';
    private $session;

    public function __construct($config = [])
    {
        parent::__construct($config);
        $this->session = Yii::$app->session;
    }

    public function authenticate($user, $request, $response)
    {

        if ($this->session->has(self::SESSION_KEY)) {
            $this->session->remove(self::SESSION_KEY);
            return parent::authenticate($user, $request, $response);
        }

        $this->session->set(self::SESSION_KEY, true);
        return null;
    }
}

但这需要 sessions 才能工作,因此它只能与浏览器一起使用。它不适用于 API。对于邮递员,此实现将使每个其他请求都失败并返回 401 Unauthorized。对于将使用 cookie 的 api,它会以同样的方式失败,并且对于不适用于 cookie 的 api 的每个请求都会失败。

旁注:邮递员做 keep/send cookie,所以 sessions 与邮递员一起工作。