Laravel支持通过token来获取用户登录信息

现在很多公司都在做前后端分离,而通过Api来判断用户是否登录,则是通过Token的形式。

Laravel自带的获取用户信息逻辑,是需要数据库中有一张User表。而目前很多公司的做法是,应用系统并没有这样的User表,User数据是记录在Passport系统的。

那么如何修改代码,来实现通过Token来调用Passport系统来获取用户信息呢?下面我来讲讲。

Laravel的默认路由里,api.phpmiddleware是这样配置的:‘middleware’=>’auth:api’

这个“auth:api”是什么意思呢?

auth对应的是app\Http\Kernel.php里的$routeMiddleware变量的auth这个key,也就是通过auth这个key,指到了Kernel 文件中配置的Class类。

api对应的是config\auth.php中的guards配置的api这个key的配置信息。(实际上api代表的是auth对应的那个类的参数,同学们看下auth那个类的源代码就明白了)

那么我们来看看config/auth.php中的guards配置吧。

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

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

其中token代表的是TokenGuard.php,有兴趣的朋友可以看看 {project}/vendor/laravel/framework/src/Illuminate/Auth/TokenGuard.php 这段源码。

providerusers,对应的是config\auth.php中的providers中的配置里,users的配置内容。如果我们要自定义一个用户提供器,可以这么写:

    'providers' => [
        // 'users' => [
        //     'driver' => 'eloquent',
        //     'model' => App\User::class,
        // ],
        'users' => [
            'driver' => 'our_provider'
        ],
        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

我定义了一个our_provider的用户提供器,接着我们来实现它。(关于自定义providers和自定义guards的说明,可以看看官方文档。但是官网写的太少了,很多人看不明白,我这里就直接贴代码给你看)

首先,需要在app/Providers/AuthServiceProvider.php文件中的boot方法里加上一段代码,如下:

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Auth::provider('our_provider', function($app, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\UserProvider...

            return new App\Authentication\UserProvider();
        });
    }

我在app目录下新建了一个文件夹,叫Authentication,里面新建了两个类,User类和UserProvider类。上面的代码里,最后return的就是我新建的UserProvider类。

通过查看TokenGuard的user方法,我得知,token守卫是通过retrieveByCredentials方法来返回用户信息的,所以我们的UserProvider要着重实现这个方法。

以下是代码例子:

<?php
namespace App\Authentication;

use App\Repositories\AuthRepository;
use Illuminate\Contracts\Auth\UserProvider as IlluminateUserProvider;
use Illuminate\Contracts\Auth\Authenticatable;

class UserProvider implements IlluminateUserProvider{
    /**
     * @param  mixed $identifier
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveById($identifier)
    {
        // Get and return a user by their unique identifier
    }

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

    /**
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  string $token
     * @return void
     */
    public function updateRememberToken(Authenticatable $user, $token)
    {
        // Save the given "remember me" token for the given user
    }

    /**
     * Retrieve a user by the given credentials.
     *
     * @param  array $credentials
     * @return \Illuminate\Contracts\Auth\Authenticatable|null
     */
    public function retrieveByCredentials(array $credentials)
    {
        //根据通行证去返回用户信息
        $user = null;
        if(isset($credentials['api_token'])){
            $token_info = AuthRepository::getTokenInfo($credentials['api_token']);
            if($token_info){
                $user = new User();
                $user->setAttributes($token_info['user_info']);
            }
        }
        return $user;
    }

    /**
     * Validate a user against the given credentials.
     *
     * @param  \Illuminate\Contracts\Auth\Authenticatable $user
     * @param  array $credentials
     * @return bool
     */
    public function validateCredentials(Authenticatable  $user, array $credentials)
    {
        // Check that given credentials belong to the given user
    }

}

我在retrieveByCredentials方法中根据api_token参数,然后去调用相关信息拿到用户信息,最后返回一个User类。记住,这里的User类也是我新建的,它必须继承Authenticatable接口。

以下是User类代码:

<?php

namespace App\Authentication;

use Illuminate\Contracts\Auth\Authenticatable;

class User implements Authenticatable
{
    private $attributes = array();

    public function setAttributes($attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * @return string
     */
    public function getAuthIdentifierName()
    {
        // Return the name of unique identifier for the user (e.g. "id")
        return 'id';
    }

    /**
     * @return mixed
     */
    public function getAuthIdentifier()
    {
        // Return the unique identifier for the user (e.g. their ID, 123)
        $identifier_name = $this->getAuthIdentifierName();
        return $this->attributes[$identifier_name];
    }

    /**
     * @return string
     */
    public function getAuthPassword()
    {
        // Returns the (hashed) password for the user
    }

    /**
     * @return string
     */
    public function getRememberToken()
    {
        // Return the token used for the "remember me" functionality
    }

    /**
     * @param  string $value
     * @return void
     */
    public function setRememberToken($value)
    {
        // Save a new token user for the "remember me" functionality
    }

    /**
     * @return string
     */
    public function getRememberTokenName()
    {
        // Return the name of the column / attribute used to store the "remember me" token
    }
}

要注意的是,User类一定要实现两个方法,分别是getAuthIdentifierNamegetAuthIdentifier

  • getAuthIdentifierName方法,返回User类的主键名称。
  • getAuthIdentifier方法,返回User类的主键值。

我们在Laravel调用Auth::id(),其实调用的就是getAuthIdentifier这个方法。

只要完成这些步骤,就可以试试用Auth::user()来获取当前用户信息了。

 

本文是我自己查阅了一些资料整理得来,如需转载,请附注原文出处。有疑问,请给我留言。

发表回复