多个模型如何认证共用 REST API?
1. 运行环境
1). 当前使用的 Laravel 版本?
Laravel Framework 8.83.27
2). 当前使用的 php/php-fpm 版本?
使用 docker 运行环境
PHP 版本:
PHP 7.3.33 (cli) (built: Mar 18 2022 04:33:02) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.33, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.33, Copyright (c) 1999-2018, by Zend Technologies
with Zend OPcache v7.3.33, Copyright (c) 1999-2018, by Zend Technologies
php-fpm 版本:
PHP 7.3.33 (fpm-fcgi) (built: Mar 18 2022 04:33:13)
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.33, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.3.33, Copyright (c) 1999-2018, by Zend Technologies
3). 当前系统
macOS 12.7.6
4). 业务环境
开发环境
5). 相关软件版本
nginx version: nginx/1.27.0
mysql Ver 8.3.0 for macos12.6 on x86_64 (Homebrew)
2. 问题描述?
在一个系统中,有2个角色:学生和老师,分别对应 student 表和 teacher 表。有一个文章模块接口分别供学生和老师使用。
路由配置:
Route::middleware('auth:student')->prefix('v1')->group(function() {
Route::get('student/article/list', 'ArticleController@list');
Route::post('student/article/upsert', 'ArticleController@upsert');
Route::get('student/article/detail/{id}', 'ArticleController@detail');
Route::post('student/article/delete', 'ArticleController@delete');
});
Route::middleware('auth:teacher')->prefix('v1')->group(function() {
Route::get('teacher/article/list', 'ArticleController@list');
Route::post('teacher/article/upsert', 'ArticleController@upsert');
Route::get('teacher/article/detail/{id}', 'ArticleController@detail');
Route::post('teacher/article/delete', 'ArticleController@delete');
});
auth.php 配置
return [
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'student' => [
'driver' => 'jwt',
'provider' => 'student'
],
'teacher' => [
'driver' => 'jwt',
'provider' => 'teacher',
'hash' => true,
],
],
'providers' => [
'student' => [
'driver' => 'eloquent',
'model' => App\Student::class,
],
'teacher' => [
'driver' => 'eloquent',
'model' => App\Teacher::class,
],
],
];
ArticleController 通过 Auth::user()可以获取当前用户的对象 App\Student
或App\Teacher
3. 您期望得到的结果?
文章接口是重复的,现在想合并 2 个分组的接口如下。 用户认证如何配置?
Route::middleware('auth:xxxx')->prefix('v1')->group(function() {
Route::get('/article/list', 'ArticleController@list');
Route::post('/article/upsert', 'ArticleController@upsert');
Route::get('/article/detail/{id}', 'ArticleController@detail');
Route::post('/article/delete', 'ArticleController@delete');
});
4. 您实际得到的结果?
一种实现方法:
routes.php
Route::middleware('auth:common_user')->prefix('v1')->group(function() {
Route::get('/article/list', 'ArticleController@list');
Route::post('/article/upsert', 'ArticleController@upsert');
Route::get('/article/detail/{id}', 'ArticleController@detail');
Route::post('/article/delete', 'ArticleController@delete');
});
auth.php
return [
'guards' => [
'student' => [
'driver' => 'jwt',
'provider' => 'student'
],
'teacher' => [
'driver' => 'jwt',
'provider' => 'teacher',
'hash' => true,
],
'common_user' => [
'driver' => 'common_user',
'provider' => 'common_user',
'hash' => true
],
],
'providers' => [
'student' => [
'driver' => 'eloquent',
'model' => App\Student::class,
],
'teacher' => [
'driver' => 'eloquent',
'model' => App\Teacher::class,
],
];
];
AppServiceProvider.php
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Auth;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
// driver common_user 实现
Auth::extend('common_user', function($app, $name, $config){
// 解析 token,判断当前用户类型
$configProvider = $config['provider'];
swtich(用户类型) {
case 'student':
$configProvider = 'student';
break;
case 'teacher':
$configProvider = 'teacher';
break;
}
// 使用了 tymon/jwt-auth 库,下面的代码可以在源码中找到,这里主要是替换了 configProvider
$provider = $app['auth']->createUserProvider($configProvider);
$guard = new JWTGuard($app['tymon.jwt'], $provider, $app['request']);
$app->refresh('request', $guard, 'setRequest');
return $guard;
});
}
}
推荐文章: