介绍
本章略长,采用了 3 种创建 token 方式,读者可以选择任意一节阅读,但本人建议全部看完,掌握多种生成 token 方式何乐而不为呢。
准备工作
- 创建 Laravel 项目并命名为 example-app
composer create-project laravel/laravel example-app
cd example-app
php artisan serve
没有特殊情况的话可以看到项目已正常运行输出
Starting Laravel development server: http://127.0.0.1:8000
- 本章所使用的 php 版本是 7.3
- 本章所使用的 Laravel 版本是 8X ,Laravel 7X 没有试过。
1. 使用 Sanctrum
Laravel 默认采用 web session 认证机制,没有提供 api 认证,但最新版 Laravel 中内置了 santum,它是专门用来 api 认证生成 token 的扩展包,不过需要自己配置才能使用。
1.1 配置数据库
sanctum
对 token 的管理是在数据库中,我们还需要到 .env
环境变量文件里进行配置
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
# 填上你的数据库名、数据库用户、数据库密码
DB_DATABASE=product
DB_USERNAME=root
DB_PASSWORD=123456
1.2 安装 sanctum
1.2.1 下载 sanctum
提示:最新 Laravel 已经提前下载好 sanctum 我们可以在 compose.json 中查看,如果没有找到则可以使用下面命令下载
# 下载 sanctum
composer require laravel/sanctum
# 发布并更新配置
# 修改内容包括 migrage 、app/Models/User.php、以及 routes/api.php
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
# 生成 sanctum 定义好的表
php artisan migrate
1.2.2 配置 config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
// 新增 api 士兵
'api' => [
'driver' => 'sanctum',
'provider' => 'users',
],
],
1.3 新增创建 token 接口
routes/api.php
代码如下
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Models\User;
Route::post('/tokens/create', function (Request $request) {
# 创建用户,这里写死作为案例。
$user = User::create([
'name' => 'cookcyq',
'email' => '[email protected]',
'password' => Hash::make('123457')
]);
# 给 cookcyq 用户生成 token, $key 是秘钥,平时秘钥一定设置复杂点,这里仅作为案例。
$key = 'hello';
$token = $user->createToken($key);
# 返回
return ['token' => $token->plainTextToken];
});
接下来使用 postman 访问 http://localhost:8000/api/tokens/create
注意要带上 api 前缀
效果如图:
可以看到成功创建用户并返回 token,现在来看看users
表是存在此用户
再来看看 personal_access_tokens
表,这个表就是 sanctum 定义的,我们来看看是否存放用户对应的 token 相关字段信息
如图所示一切正常,你可能注意到 personal_access_tokens
表里的 token 内容与 postman 返回的token 不一致,这个无需担心,这是 sanctum 自己要处理的逻辑,我们只需拿接口返回的 token 去使用即可。
1.4 新增获取用户信息接口
拿到 token 后,我们开始新增用户信息接口来验证 token 是否对应上该用户。
routes/api.php
代码如下
// ...
// 以上省略
// 新增
Route::post('/getProfile', function (Request $request) {
// 获取用户信息:sanctum 帮我们从数据库中寻找,它能寻找是因为我们已经在 auth.php 中配置好 provider:users 对应的 Elquent User 模型
$user = $request->user();
// 也可以用以下方式获取
// $user = auth()->guard('api')->user();
return response([
'data' => $user
]);
})->middleware('auth:api');
现在拿刚才接口返回的 token 去访问http://localhost:8000/api/getProfile
sanctum 是采用 Bearer Token
形式,需要带上 Bearer 前缀,header 请求格式如下:
Authorization: Bearer 1|Vjq5FOkhnwX6laVxNLE2YAEZTrMopmQeHtC4KyA2
访问效果图:
可以看到根据 token 可以返回对应的用户信息,现在我们用无效的 token 试试
注意:在使用前,确保 postman 里的 header 设置为 Accept:application/json
否则会报如下错误:Route[login] not defined.
这个报错是因为 Laravel 默认情况下会对 Access 做出相应的认证判断,由于 postman header 默认设置为 Access: * ,而 Laravel 默认的授权认证是采用 web session 机制,所以未授权的用户都会重定向到 login 页面,触发逻辑代码可在 app/http/Middleware/Authenticate.php
中看到
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
由于我们是针对 api 不是 web ,不需要重定向,这里可以重写一下逻辑。
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
// 换成这句
return response([
'msg' => '请登录',
'code' => -10000
]);
}
<