Yii2 REST API BasicAuth not working

2019-04-15 04:15发布

问题:

Im implementing REST API Authentication module as following step 1. Create user by Admin 2. First tim: login by Basic Auth to return access_token 3. Use access_token at step 2 to Auth user by. QueryParamAuth

as this instruction it work with QueryParamAuth https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-authentication.md

But it not work at step2. Auth by BasicAuth I debug it. $this->auth always return null. Although $username and $password right

class HttpBasicAuth extends AuthMethod
/**
 * @var callable a PHP callable that will authenticate the user with the HTTP basic auth information.
 * The callable receives a username and a password as its parameters. It should return an identity object
 * that matches the username and password. Null should be returned if there is no such identity.
 *
 * The following code is a typical implementation of this callable:
 *
 * ```php
 * function ($username, $password) {
 *     return \app\models\User::findOne([
 *         'username' => $username,
 *         'password' => $password,
 *     ]);
 * }
 * ```
 *
 * If this property is not set, the username information will be considered as an access token
 * while the password information will be ignored. The [[\yii\web\User::loginByAccessToken()]]
 * method will be called to authenticate and login the user.
 */
public $auth;
public function authenticate($user, $request, $response)
{
    $username = $request->getAuthUser();
    $password = $request->getAuthPassword();
    if ($this->auth) {
        if ($username !== null || $password !== null) {
            $identity = call_user_func($this->auth, $username, $password);
            var_dump($identity);
            die();
            if ($identity !== null) {
                $user->switchIdentity($identity);
            } else {
                $this->handleFailure($response);
            }
            return $identity;
        }
    } elseif ($username !== null) {
        $identity = $user->loginByAccessToken($username, get_class($this));
        if ($identity === null) {
            $this->handleFailure($response);
        }
        return $identity;
    }

    return null;
}

My question is how can i implement $this->auth function?

回答1:

HTTP Basic Auth

// controller code

Way 1: user Auth using auth-token

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
    ];
    return $behaviors;
}

Above code will validate user by access token (as mentioned in the doc)

when window prompts to enter username & password

username: hErEaccE55T0ken

password:

Way 2: To implement custom auth using username & password, sample code (chris code works)

i m using user_email, user_password

public $user_password;


public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
        'auth' => [$this, 'auth']
    ];
    return $behaviors;
}

/**
 * Finds user by user_email and user_password
 *
 * @param string $username
 * @param string $password
 * @return static|null
 */
public function Auth($username, $password) {
    // username, password are mandatory fields
    if(empty($username) || empty($password))
        return null;

    // get user using requested email
    $user = \app\models\User::findOne([
        'user_email' => $username,
    ]);

    // if no record matching the requested user
    if(empty($user))
        return null;

    // hashed password from user record
    $this->user_password = $user->user_password;

    // validate password
    $isPass = \app\models\User::validatePassword($password);

    // if password validation fails
    if(!$isPass)
        return null;

    // if user validates (both user_email, user_password are valid)
    return $user;
}


回答2:

I implement HttpBasicAuth->auth in my controller where I attach HttpBasicAuth as a behavior like so:

class MyController extends Controller
{
    public function behaviors()
    {
        $behaviors = parent::behaviors();

        $behaviors['authenticator'] = [
            'class' => HttpBasicAuth::className(),
            'auth' => [$this, 'auth']
        ]

        return $behaviors;
    }

    public function auth($username, $password)
    {
        // Do whatever authentication on the username and password you want.
        // Create and return identity or return null on failure
    }

    // ... Action code ...
}