场景
. 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 ' }}">