Внедрение деталей аутентификации пользователя API пользовательского интерфейса на основе Laravel Auth

база данных Микросервисы API Laravel

На основе laravel по умолчаниюauthРеализовать API-аутентификацию

Микросервисы становятся все более популярными сейчас, многие вещи разделены на независимые системы, и нет прямой связи между каждой системой, таким образом, если мы делаем аутентификацию пользователей, мы должны быть едиными и независимыми.用户认证Система, а не каждая бизнес-система, должна переписывать вещи, связанные с аутентификацией пользователей, но возникает другая проблема.laravelдефолтauth 认证Он основан на базе данных, а что, если вам нужна микросервисная архитектура?

Код реализации выглядит следующим образом:

Пользовательский интерфейс:

// 通过唯一标示符获取认证模型
public function retrieveById($identifier);
// 通过唯一标示符和 remember token 获取模型
public function retrieveByToken($identifier, $token);
// 通过给定的认证模型更新 remember token
public function updateRememberToken(Authenticatable $user, $token);
// 通过给定的凭证获取用户,比如 email 或用户名等等
public function retrieveByCredentials(array $credentials);
// 认证给定的用户和给定的凭证是否符合
public function validateCredentials(Authenticatable $user, array $credentials);

LaravelПо умолчанию их дваuser provider : DatabaseUserProvider & EloquentUserProvider. DatabaseUserProvider Illuminate\Auth\DatabaseUserProvider

Получите модель аутентификации непосредственно из таблицы базы данных.

EloquentUserProvider Illuminate\Auth\EloquentUserProvider

Получите модель аутентификации через красноречивую модель


Основываясь на приведенных выше знаниях, вы можете знать, что настроить аутентификацию очень просто.

настроитьProvider

Создайте пользовательскую модель аутентификации, реализующую интерфейс Authenticatable;

App\Auth\UserProvider.php

<?php

namespace App\Auth;

use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider as Provider;

class UserProvider implements Provider
{

    /**
     * Retrieve a user by their unique identifier.
     * @param  mixed $identifier
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveById($identifier)
    {
        return app(User::class)::getUserByGuId($identifier);
    }

    /**
     * Retrieve a user by their unique identifier and "remember me" token.
     * @param  mixed  $identifier
     * @param  string $token
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByToken($identifier, $token)
    {
        return null;
    }

    /**
     * Update the "remember me" token for the given user in storage.
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  string                                     $token
     * @return bool
     */
    public function updateRememberToken(Authenticatable $user, $token)
    {
        return true;
    }

    /**
     * Retrieve a user by the given credentials.
     * @param  array $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        if ( !isset($credentials['api_token'])) {
            return null;
        }

        return app(User::class)::getUserByToken($credentials['api_token']);
    }

    /**
     * Rules a user against the given credentials.
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  array                                      $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable $user, array $credentials)
    {
        if ( !isset($credentials['api_token'])) {
            return false;
        }

        return true;
    }
}

Аутентифицируемый интерфейс:

Illuminate\Contracts\Auth\AuthenticatableAuthenticatable определяет интерфейс, который должна реализовать модель или класс, которые могут использоваться для аутентификации, то есть, если вам нужно использовать пользовательский класс для аутентификации, вам необходимо реализовать методы, определенные этим интерфейсом.

<?php
.
.
.
// 获取唯一标识的,可以用来认证的字段名,比如 id,uuid
public function getAuthIdentifierName();
// 获取该标示符对应的值
public function getAuthIdentifier();
// 获取认证的密码
public function getAuthPassword();
// 获取remember token
public function getRememberToken();
// 设置 remember token
public function setRememberToken($value);
// 获取 remember token 对应的字段名,比如默认的 'remember_token'
public function getRememberTokenName();
.
.
.

определено в LaravelAuthenticatable trait, который также используется по умолчанию для аутентификации Laravel.UserЧерта, используемая моделью, эта черта определяетUserИдентификатор аутентификации по умолчанию для модели — «id», а поле пароля —password,remember tokenСоответствующее полеremember_tokenи т.п. ​ путем переписыванияUserЭти методы модели могут изменять некоторые настройки.

Внедрение пользовательской модели аутентификации

App\Models\User.php

<?php

namespace App\Models;

use App\Exceptions\RestApiException;
use App\Models\Abstracts\RestApiModel;
use Illuminate\Contracts\Auth\Authenticatable;

class User extends RestApiModel implements Authenticatable
{

    protected $primaryKey = 'guid';

    public $incrementing = false;

    protected $keyType = 'string';

    /**
     * 获取唯一标识的,可以用来认证的字段名,比如 id,guid
     * @return string
     */
    public function getAuthIdentifierName()
    {
        return $this->primaryKey;
    }

    /**
     * 获取主键的值
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        $id = $this->{$this->getAuthIdentifierName()};
        return $id;
    }


    public function getAuthPassword()
    {
        return '';
    }

    public function getRememberToken()
    {
        return '';
    }

    public function setRememberToken($value)
    {
        return true;
    }

    public function getRememberTokenName()
    {
        return '';
    }

    protected static function getBaseUri()
    {
        return config('api-host.user');
    }

    public static $apiMap = [
        'getUserByToken' => ['method' => 'GET', 'path' => 'login/user/token'],
        'getUserByGuId'  => ['method' => 'GET', 'path' => 'user/guid/:guid'],
    ];


    /**
     * 获取用户信息 (by guid)
     * @param string $guid
     * @return User|null
     */
    public static function getUserByGuId(string $guid)
    {
        try {
            $response = self::getItem('getUserByGuId', [
                ':guid' => $guid
            ]);
        } catch (RestApiException $e) {
            return null;
        }

        return $response;
    }


    /**
     * 获取用户信息 (by token)
     * @param string $token
     * @return User|null
     */
    public static function getUserByToken(string $token)
    {
        try {
            $response = self::getItem('getUserByToken', [
                'Authorization' => $token
            ]);
        } catch (RestApiException $e) {
            return null;
        }

        return $response;
    }
}

надRestApiModelнаша компанияGuzzleИнкапсуляция проекта php между различными системамиapiЗвоните.Код раскрывать не удобно.

Охранный интерфейс

Illuminate\Contracts\Auth\Guard

GuardИнтерфейс определяет реализацию, котораяAuthenticatable(Аутентифицируемый) Методы аутентификации для моделей или классов и некоторых часто используемых интерфейсов.

// 判断当前用户是否登录
public function check();
// 判断当前用户是否是游客(未登录)
public function guest();
// 获取当前认证的用户
public function user();
// 获取当前认证用户的 id,严格来说不一定是 id,应该是上个模型中定义的唯一的字段名
public function id();
// 根据提供的消息认证用户
public function validate(array $credentials = []);
// 设置当前用户
public function setUser(Authenticatable $user);

Интерфейс StatefulGuard

Illuminate\Contracts\Auth\StatefulGuard

StatefulGuardИнтерфейс наследуется отGuardинтерфейс, кромеGuardВ дополнение к некоторым базовым интерфейсам, определенным в нем, также добавляются интерфейсы с отслеживанием состояния.Guard.

Новые добавленные интерфейсы:

// 尝试根据提供的凭证验证用户是否合法
public function attempt(array $credentials = [], $remember = false);
// 一次性登录,不记录session or cookie
public function once(array $credentials = []);
// 登录用户,通常在验证成功后记录 session 和 cookie 
public function login(Authenticatable $user, $remember = false);
// 使用用户 id 登录
public function loginUsingId($id, $remember = false);
// 使用用户 ID 登录,但是不记录 session 和 cookie
public function onceUsingId($id);
// 通过 cookie 中的 remember token 自动登录
public function viaRemember();
// 登出
public function logout();

Laravel3 предоставляются по умолчаниюguard:RequestGuard,TokenGuard,SessionGuard.

RequestGuard

Illuminate\Auth\RequestGuard

RequestGuard — очень простой сторож, RequestGuard аутентифицируется путем передачи замыкания. позвонивAuth::viaRequestДобавьте пользовательский RequestGuard.

SessionGuard

Illuminate\Auth\SessionGuard

SessionGuard — это защита по умолчанию для веб-аутентификации Laravel.

TokenGuard

Illuminate\Auth\TokenGuard

TokenGuard подходит для проверки подлинности API без сохранения состояния с помощью проверки подлинности токена.

Реализовать настройкуGuard

App\Auth\UserGuard.php

<?php

namespace App\Auth;

use Illuminate\Http\Request;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;

class UserGuard implements Guard

{
    use GuardHelpers;

    protected $user = null;

    protected $request;

    protected $provider;

    /**
     * The name of the query string item from the request containing the API token.
     *
     * @var string
     */
    protected $inputKey;

    /**
     * The name of the token "column" in persistent storage.
     *
     * @var string
     */
    protected $storageKey;

    /**
     * The user we last attempted to retrieve
     * @var
     */
    protected $lastAttempted;

    /**
     * UserGuard constructor.
     * @param UserProvider $provider
     * @param Request      $request
     * @return void
     */
    public function __construct(UserProvider $provider, Request $request = null)
    {
        $this->request = $request;
        $this->provider = $provider;
        $this->inputKey = 'Authorization';
        $this->storageKey = 'api_token';
    }

    /**
     * Get the currently authenticated user.
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function user()
    {
        if(!is_null($this->user)) {
            return $this->user;
        }

        $user = null;

        $token = $this->getTokenForRequest();

        if(!empty($token)) {
            $user = $this->provider->retrieveByCredentials(
                [$this->storageKey => $token]
            );
        }

        return $this->user = $user;
    }

    /**
     * Rules a user's credentials.
     * @param  array $credentials
     * @return bool
     */
    public function validate(array $credentials = [])
    {
        if (empty($credentials[$this->inputKey])) {
            return false;
        }

        $credentials = [$this->storageKey => $credentials[$this->inputKey]];

        $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

        return $this->hasValidCredentials($user, $credentials);
    }

    /**
     * Determine if the user matches the credentials.
     * @param  mixed $user
     * @param  array $credentials
     * @return bool
     */
    protected function hasValidCredentials($user, $credentials)
    {
        return !is_null($user) && $this->provider->validateCredentials($user, $credentials);
    }


    /**
     * Get the token for the current request.
     * @return string
     */
    public function getTokenForRequest()
    {
        $token = $this->request->header($this->inputKey);

        return $token;
    }

    /**
     * Set the current request instance.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return $this
     */
    public function setRequest(Request $request)
    {
        $this->request = $request;

        return $this;
    }
}

Добавьте следующий код в метод загрузки AppServiceProvider:App\Providers\AuthServiceProvider.php

<?php
.
.
.
// auth:api -> token provider.
Auth::provider('token', function() {
	return app(UserProvider::class);
});

// auth:api -> token guard.
// @throw \Exception
Auth::extend('token', function($app, $name, array $config) {
	if($name === 'api') {
		return app()->make(UserGuard::class, [
			'provider' => Auth::createUserProvider($config['provider']),
			'request'  => $app->request,
		]);
	}
	throw new \Exception('This guard only serves "auth:api".');
});
.
.
.
  • существуетconfig\auth.phpДобавить обычай в массив Guardsguard, таможня состоит из двух частей:driverа такжеprovider.

  • настраиватьconfig\auth.phpdefaults.guard этоapi.

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'token',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        'token' => [
            'driver' => 'token',
            'model' => App\Models\User::class,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

Как использовать:

file

оригинальныйадресСправочная статья:адрес

Это первый раз, когда я пишу статью с таким количеством слов, пожалуйста, простите меня, если письмо не очень хорошо!!