1.创先一个新项目
composer create-project --prefer-dist laravel/laravel my-app
2.配置好数据库后迁移数据
php artisan migrate
3.让我们为 User 模型创建一个 Seeder。我们稍后会需要它来测试登录过程。
php artisan make:seeder UsersTableSeeder
4.现在,让我们在 database/seeds/UsersTableSeeder.php 的 run() 方法中,插入以下代码
public function run()
{
DB::table('users')->insert([
'name' => 'John Doe',
'email' => 'john@doe.com',
'password' => Hash::make('password')
]);
}
5.给 users 表生成 user, 让我们运行:
php artisan db:seed --class=UsersTableSeeder
6.现在我们的数据库里有一个新用户叫 "John Doe",邮箱是 "john@doe.com",密码是 "password",请直接复制users 表到admins下文需要测试用到。
?
7.使用composer安装jwt-auth
composer require tymon/jwt-auth
8.laravel 版本大于等于 5.5 版本可以省略此步骤 注册服务提供者 config/app.php
'providers' => [
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]
'aliases' => [
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
]
9.发布生成配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
运行后config文件下自动生成jwt.php
10.使用以下命令生成密
php artisan jwt:secret
完成后会在.env文件中自动生成密匙
JWT_SECRET=pzBAAzjt1fOhBjKpuuN0OSNhDdeYHnhnLLkWDD68LiDcNIk14CFjDJdjJ1f
11.配置多 guard 来区分认证 打开 config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 默认是 token
'provider' => 'users',
],
// 新增admins 模块
'admin' => [
'driver' => 'jwt',
'provider' => 'admins',
]
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
]
],
12.更改相应的 Model 文件。App\Models\User.php 让User.php实现Tymon\JWTAuth\Contracts\JWTSubject类
实现两个方法:getJWTIdentifier()和getJWTCustomClaims()
文件/app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 获取会储存到 jwt 声明中的标识
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* 返回包含要添加到 jwt 声明中的自定义键值对数组
* @return array
*/
public function getJWTCustomClaims()
{
return ['role' => 'user'];
}
}
13.App\Models\Admin.php
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Admin extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 获取会储存到 jwt 声明中的标识
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* 返回包含要添加到 jwt 声明中的自定义键值对数组
* @return array
*/
public function getJWTCustomClaims()
{
return ['role' => 'admin'];
}
}
14.在 router/api.php 文件中创建路由信息
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
# 普通用户登录
Route::group([
'prefix' => 'auth'
], function () {
Route::post('login', [\App\Http\Controllers\AuthController::class,'login']);
Route::post('logout', [\App\Http\Controllers\AuthController::class,'logout']);
Route::post('refresh', [\App\Http\Controllers\AuthController::class,'refresh']);
Route::post('me', [\App\Http\Controllers\AuthController::class,'me'])->name('me')->middleware(['jwt.role:user', 'jwt.auth']);
//如果不走中间件则不用加—>middleware
});
# 后台用户登录
Route::group([
'prefix' => 'admin',
'namespace' => 'Admin'
], function () {
Route::post('login', [\App\Http\Controllers\Admin\LoginController::class,'login']);
Route::post('logout', [\App\Http\Controllers\Admin\LoginController::class,'logout']);
Route::post('refresh', [\App\Http\Controllers\Admin\LoginController::class,'refresh']);
Route::post('me', [\App\Http\Controllers\Admin\LoginController::class,'me'])->name('me')->middleware(['jwt.role:admin', 'jwt.auth']);
});
15.创建相应的控制器AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
class AuthController extends Controller
{
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
/**
* @return JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function me()
{
return response()->json(auth('api')->user());
}
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* @param $token
* @return JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
15.Admin/LoginController.php
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
class LoginController extends Controller
{
public function __construct()
{
$this->middleware('auth:admin', ['except' => ['login']]);
}
/**
* @return JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('admin')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function me()
{
return response()->json(auth('admin')->user());
}
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* @param $token
* @return JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
16.(如果需要检查token对应哪个平台)创建中间件检测当前 token 对应的是哪个平台
php artisan make:middleware JWTRoleAuth
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class JWTRoleAuth extends BaseMiddleware
{
/**
* JWT 检测当前登录的平台
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param null $role
* @return mixed
*/
public function handle($request, Closure $next, $role = null)
{
try {
// 解析token角色
$tokenRole = $this->auth->parseToken()->getClaim('role');
} catch (JWTException $e) {
/**
* token解析失败,说明请求中没有可用的token。
* 为了可以全局使用(不需要token的请求也可通过),这里让请求继续。
* 因为这个中间件的责职只是校验token里的角色。
*/
return $next($request);
}
// 判断token角色。
if ($tokenRole != $role) {
throw new UnauthorizedHttpException('jwt-auth', 'User role error');
}
return $next($request);
}
}
17.并将中间件加入app/Http/Kernel.php
protected $routeMiddleware = [
...
'jwt.role' => JWTRoleAuth::class,
];
18.用postman测试接口
19.POST dev.api.sanctum.cc/api/auth/login
email:john@doe.com password:password
``JSON
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZXYuYXBpLnNhbmN0dW0uY2NcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE2Mjk3OTE4ODQsImV4cCI6MTYyOTc5NTQ4NCwibmJmIjoxNjI5NzkxODg0LCJqdGkiOiJVb0Z5YzJmcVhjM1J5NllpIiwic3ViIjoxLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3Iiwicm9sZSI6InVzZXIifQ.2x4gyZ_eJ8nMlcRs8agcrYSHyKMT2t6KhSqPezZHcB0",
"token_type": "bearer",
"expires_in": 3600
}
``
20.POST dev.api.sanctum.cc/api/auth/me
Headers Accept:application/json Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZXYuYXBpLnNhbmN0dW0uY2NcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE2Mjk3OTE4ODQsImV4cCI6MTYyOTc5NTQ4NCwibmJmIjoxNjI5NzkxODg0LCJqdGkiOiJVb0Z5YzJmcVhjM1J5NllpIiwic3ViIjoxLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3Iiwicm9sZSI6InVzZXIifQ.2x4gyZ_eJ8nMlcRs8agcrYSHyKMT2t6KhSqPezZHcB0
``json
{
"id": 1,
"name": "John Doe",
"email": "john@doe.com",
"email_verified_at": null,
"created_at": null,
"updated_at": null
}
``
21.POST dev.api.sanctum.cc/api/admin/login
?
email:zhansan@doe.com password:password
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZXYuYXBpLnNhbmN0dW0uY2NcL2FwaVwvYWRtaW5cL2xvZ2luIiwiaWF0IjoxNjI5ODU5OTk1LCJleHAiOjE2Mjk4NjM1OTUsIm5iZiI6MTYyOTg1OTk5NSwianRpIjoia2VwS3N3VVMwU3d4RzNEbSIsInN1YiI6MSwicHJ2IjoiZGY4ODNkYjk3YmQwNWVmOGZmODUwODJkNjg2YzQ1ZTgzMmU1OTNhOSIsInJvbGUiOiJhZG1pbiJ9.Y0DZjBiXk137I3UHBptLs0O7TEKq4Sjh9Lw790yYXwM",
"token_type": "bearer",
"expires_in": 3600
}
22.POST dev.api.sanctum.cc/api/admin/me
Headers Accept:application/json Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9kZXYuYXBpLnNhbmN0dW0uY2NcL2FwaVwvYWRtaW5cL2xvZ2luIiwiaWF0IjoxNjI5ODU5OTk1LCJleHAiOjE2Mjk4NjM1OTUsIm5iZiI6MTYyOTg1OTk5NSwianRpIjoia2VwS3N3VVMwU3d4RzNEbSIsInN1YiI6MSwicHJ2IjoiZGY4ODNkYjk3YmQwNWVmOGZmODUwODJkNjg2YzQ1ZTgzMmU1OTNhOSIsInJvbGUiOiJhZG1pbiJ9.Y0DZjBiXk137I3UHBptLs0O7TEKq4Sjh9Lw790yYXwM
?返回结果
{
"id": 1,
"name": "zhangsan",
"email": "zhangsan@doe.com",
"email_verified_at": null,
"created_at": null,
"updated_at": null
}
Successfull !
|