laravel5.5 api_token源码解析 && 实现快捷解决api访问的无认证状态

场景

. laravel5.5的API认证分为两种 
    1.  passport  
    2.  api_token 
/*
|--------------------------------------------------------------------------
| 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' => 'users',
    ],
],

分析

. api_token的配置分成两部分
1.   给每个用户生成唯一的api_token
2.  前端配置,使 前端的每次请求带上响应的header
3. 执行校验权限操作的是类`vendor/laravel/framework/src/Illuminate/Auth/TokenGuard.php`

执行认证的方法是 TokenGuard::user(),具体实现分成两步

第一步 获取token(TokenGuard::getTokenForRequest)

首先 query string 中获取api_token字段
然后尝试在payload 中获取api_token字段
接着尝试在header 下标Authorization 中获取api_token, 它的值是”Bearer ” + $api_token,
最后尝试在header下标记 PHP_AUTH_PW 的值作为token

第二步 根据token 获取登陆用户

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

需要注意的是 传入的$inputKey 和存在数据库中$storageKey 是固定的api_token

解决

解决思路

. 采用TokenGuard中在header中获取api_token的方式(`Authorization`)

解决

. 修改数据库 users 表新增字段 api_token
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddApiTokenToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('api_token', 64)->comment('api_token 唯一的字段');
            $table->unique('api_token');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('api_token');
        });
    }
}
    . 修改新建用户, 给用户添加唯一的api_token && UserModel 需要加$fillable
    . js 请求设置header 'Authorization'
      这部分我是使用的是vue-resource  所以我使用的是如下的设置

app.js

// 引入vue-rsource
let VueResource = require('vue-resource');
Vue.use(VueResource);

let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
    Vue.http.headers.common['X-CSRF-TOKEN'] = token.content;
    Vue.http.headers.common['Authorization'] = token.getAttribute('api_token');
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

app.blade.php

 <meta name="csrf-token" content="{{ csrf_token() }}" api_token="{{ \Auth::check() ? 'Bearer ' . \Auth::user()->api_token : 'Bearer '  }}">

猜你喜欢

转载自blog.csdn.net/cominglately/article/details/80719937