Laravel Api实现JWT Token认证
在开发Api时,处理客户端请求之前,需要对用户进行身份认证,Laravel框架默认为我们提供了一套用户认证体系,在进行web开发时,几乎不用添加修改任何代码,可直接使用,但在进行api开发时,需要我们自己去实现,并且Laravel框架默认提供的身份认证不是jwt的,需要在数据库中增加api_token字段,记录用户认证token并进行身份校验,如果需要使用jwt,无需添加字段,需要借助三方库来实现。
Token认证原理
-
客户端发送认证信息 (一般就是用户名 / 密码), 向服务器发送请求
-
服务器验证客户端的认证信息,验证成功之后,服务器向客户端返回一个 加密的 token (一般情况下就是一个字符串)
-
客户端存储 (cookie, session, app 中都可以存储) 这个 token, 在之后每次向服务器发送请求时,都携带上这个 token
-
服务器验证这个 token 的合法性,只要验证通过,服务器就认为该请求是一个合法的请求
JWT概述
token 只是一种思路,一种解决用户授权问题的思考方式,基于这种思路,针对不同的场景可以有很多种的实现。而在众多的实现中,JWT (JSON Web Token) 的实现最为流行.
JWT 这个标准提供了一系列如何创建具体 token 的方法,这些缘故方法和规范可以让我们创建 token 的过程变得更加合理和效率.
比如,传统的做法中,服务器会保存生成的 token, 当客户端发送来 token 时,与服务器的进行比对,但是 jwt 的不需要在服务器保存任何 token, 而是使用一套加密 / 解密算法 和 一个密钥 来对用户发来的 token 进行解密,解密成功后就可以得到这个用户的信息.
这样的做法同时也增加了多服务器时的扩展性,在传统的 token 验证中,一旦用户发来 token, 那么必须要先找到存储这个 token 的服务器是哪台服务器,然后由那一台服务器进行验证用户身份。而 jwt 的存在,只要每一台服务器都知道解密密钥,那么每一台服务器都可以拥有验证用户身份的能力.
这样一来,服务器就不再保存任何用户授权的信息了,也就解决了 session 曾出现的问题.
实现方法
1.安装 jwt-auth
composer require tymon/jwt-auth:dev-develop
参考文档:
https://github.com/tymondesigns/jwt-auth/wiki/Installation
2.在 config/app.php
的 providers
配置项中注册服务提供者
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
3.生成配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此命令会在 config
目录下生成 jwt.php
配置文件
4.生成密钥
php artisan jwt:secret
此命令会在你的 .env
文件中新增一行 JWT_SECRET=secret
5.创建模型
php artisan make:model Models/User
代码:
<?php namespace App\Models; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { protected $fillable = ['name', 'password']; protected $hidden = ['password', 'remember_token']; // public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
6.修改配置文件 auth.php
'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', 'hash' => false, ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class ], ],
7.实现登录注册返回token
php artisan make:controller Api/UserController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\Member; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class PassportController extends Controller { public function __construct() { $this->middleware('auth:api', ['except' => ['register', 'login']]); } /** * 用户注册 */ public function register(Request $request) { // jwt token $credentials = [ 'name' => $request->name, 'password' => Hash::make($request->password) ]; $user = User::create($credentials); if($user){ $token = = JWTAuth::fromUser($user); return $this->responseWithToken($token); } } /** * 用户登录 */ public function login(Request $request) { // todo 用户登录逻辑 // jwt token $credentials = $request->only('name', 'password'); if (!$token = JWTAuth::attempt($credentials)) { return response()->json(['result'=>'failed']); } return $this->responseWithToken($token); } /** * 刷新token */ public function refresh() { return $this->responseWithToken(JWTAuth::refresh()); } /** * 退出登录 */ public function logout(Request $request) { JWTAuth::logout(); } /** * 响应 */ private function responseWithToken(string $token) { $response = [ 'access_token' => $token, 'token_type' => 'Bearer', 'expires_in' => JWTAuth::factory()->getTTL() * 60 ]; return response()->json($response); } }
原文地址:https://www.stephen520.cn/blog/10255