Laravel JWT 多用户权限校验
首先安装jwt-auth:
composer require tymon/jwt-auth
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret
修改api路由文件routes/api.php:
// Route::post('/teacher/register', 'TeachersController@register');
Route::post('/teacher/login', 'TeachersController@login');
Route::group(['middleware' => 'multiauth:teacher'], function() {
Route::get('/teacher/me', 'TeachersController@me');
});
// Route::post('/student/register', 'StudentsController@register');
Route::post('/student/login', 'StudentsController@login');
Route::group(['middleware' => 'multiauth:student'], function() {
Route::get('/student/me', 'StudentsController@me');
});
修改数据库迁移文件:
php artisan migrate create_teachers_table
public function up()
{
Schema::create('teachers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 100)->unique();
$table->string('teacher_card_id', 5)->unique();
$table->string('mobile', 11)->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
php artisan migrate create_students_table
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 100)->unique();
$table->string('student_card_id', 5)->unique();
$table->string('mobile', 11)->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
修改数据库填充文件database/seeds/DatabaseSeeder.php
public function run()
{
// $this->call(UsersTableSeeder::class);
DB::table('teachers')->insert([
'name' => '教师A',
'teacher_card_id' => '81001',
'mobile' => '13500081001',
'password' => bcrypt('12345'),
]);
DB::table('teachers')->insert([
'name' => '教师B',
'teacher_card_id' => '81002',
'mobile' => '13500081002',
'password' => bcrypt('12345'),
]);
DB::table('students')->insert([
'name' => '学生甲',
'student_card_id' => '18001',
'mobile' => '13900018001',
'password' => bcrypt('12345'),
]);
DB::table('students')->insert([
'name' => '学生乙',
'student_card_id' => '18002',
'mobile' => '13900018002',
'password' => bcrypt('12345'),
]);
}
执行数据库迁移: php artisan migrate:refresh --seed
修改配置文件config/auth.php
'guards' => [
...
'teacher' => [
'driver' => 'jwt',
'provider' => 'teachers',
],
'student' => [
'driver' => 'jwt',
'provider' => 'students',
],
],
...
'providers' => [
...
'teachers' => [
'driver' => 'eloquent',
'model' => App\Teacher::class,
],
'students' => [
'driver' => 'eloquent',
'model' => App\Student::class,
],
...
],
新增模型文件app/Teacher.php
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Teacher extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'teacher_card_id', 'mobile', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return ['identity' => 'teacher'];
}
}
新增模型文件app/Student.php
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Student extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'student_card_id', 'mobile', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return ['identity' => 'student'];
}
}
新增控制器文件app/Http/Controllers/TeachersController.php
<?php
namespace App\Http\Controllers;
use Log;
use Illuminate\Http\Request;
class TeachersController extends Controller
{
// 教师登录接口
public function login(Request $request)
{
Log::info(__METHOD__." Method Started");
$credentials = $request->only('teacher_card_id', 'password');
if (!$token = auth()->guard('teacher')->attempt($credentials)) {
return response()
->json(['retcode' => '100001', 'retmsg' => '教师证号或密码错误'], 401);
}
return response()
->json(['retcode' => '000000', 'retmsg' => '登录成功'], 200)
->header('Authorization', 'Bearer '.$token); // 响应头添加token
}
// 教师信息展示接口
public function me(Request $request)
{
Log::info(__METHOD__." Method Started");
if (!$me = auth()->guard('teacher')->user()) {
return response()
->json(['retcode' => '100004', 'retmsg' => '登录异常'], 401);
}
return response()
->json(['retcode' => '000000', 'retmsg' => '请求成功',
'me' => array($me),
], 200);
}
}
新增控制器文件app/Http/Controllers/StudentsController.php
<?php
namespace App\Http\Controllers;
use Log;
use Illuminate\Http\Request;
class StudentsController extends Controller
{
// 学生登录接口
public function login(Request $request)
{
Log::info(__METHOD__." Method Started");
$credentials = $request->only('student_card_id', 'password');
if (!$token = auth()->guard('student')->attempt($credentials)) {
return response()
->json(['retcode' => '100001', 'retmsg' => '学生证号或密码错误'], 401);
}
return response()
->json(['retcode' => '000000', 'retmsg' => '登录成功'], 200)
->header('Authorization', 'Bearer '.$token); // 响应头添加token
}
// 学生信息展示接口
public function me(Request $request)
{
Log::info(__METHOD__." Method Started");
if (!$me = auth()->guard('student')->user()) {
return response()
->json(['retcode' => '100004', 'retmsg' => '登录异常'], 401);
}
return response()
->json(['retcode' => '000000', 'retmsg' => '请求成功',
'me' => array($me),
], 200);
}
}
修改中间件配置文件app/Http/Kernel.php
protected $routeMiddleware = [
...
'multiauth' => \App\Http\Middleware\MultiAuthenticate::class,
];
新增中间件文件app/Http/Middleware/MultiAuthenticate.php
<?php
namespace App\Http\Middleware;
use Log;
use Closure;
class MultiAuthenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param $identity
* @return mixed
*/
public function handle($request, Closure $next, $identity)
{
try {
if (!$request->header('Authorization')) {
return response()
->json(['retcode' => '100003', 'retmsg' => '您没有登录'], 401);
}
if ($identity != auth()->guard($identity)->payload()->get('identity')) {
return response()
->json(['retcode' => '100005', 'retmsg' => '登录身份错误'], 401);
}
if(!auth()->guard($identity)->userOrFail()) {
return response()
->json(['retcode' => '100004', 'retmsg' => '登录异常'], 401);
}
return $next($request);
}
catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
try {
$token = auth()->guard($identity)->refresh();
// auth()->guard($identity)->onceUsingId(auth()->guard($identity)->payload()->get('sub'));
}
catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()
->json(['retcode' => '100002', 'retmsg' => '登录状态已失效'], 401);
}
$request->headers->set('Authorization', 'Bearer '.$token);
return $next($request)->header('Authorization', 'Bearer '.$token);
}
catch (\Tymon\JWTAuth\Exceptions\UserNotDefinedException $e) {
$identity_name = ($identity=='teacher') ? '教师' : '学生';
return response()
->json(['retcode' => '100001', 'retmsg' => $identity_name.'证号或密码错误'], 401);
}
catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()
->json(['retcode' => '999998', 'retmsg' => '登录状态异常'], 401);
}
return response()
->json(['retcode' => '999999', 'retmsg' => '系统异常'], 401);
}
}