Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌

目录

jwt概述:

1、安装jwt

2.注册服务提供者和别名

3、发布配置文件

4.在发布的配置中生成key:

5.配置 api的验证模式

6、修改Model 

7、 配置项详解

8、自定义RefreshToken 中间件

9、注册RefreshToken 中间件

10、更新异常处理的handler

11、添加新的控制器

12、添加路由

 13、在数据库中添加数据

14、请求接口

15、请求结果


jwt概述:

JWT(JSON Web Token)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。

1、安装jwt

安装地址:https://packagist.org/packages/tymon/jwt-auth

composer require tymon/jwt-auth

2.注册服务提供者和别名

安装完成后,在配置文件 config/app.php 中注册服务提供者和别名:

'providers' => [
Tymon\JWTAuth\Providers\LaravelServiceProvider::class
]

'aliases' => [
'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
]

3、发布配置文件

在你项目根目录运行如下命令,生成config\ jwt.php 的配置文件:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

4.在发布的配置中生成key:

此命令会在你的 .env 文件中新增一行 JWT_SECRET=secret。

php artisan jwt:secret

5.配置 api的验证模式

在 config/auth.php 文件中,你需要将 guards中api['driver ']的值更新为 jwt:

    'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

6、修改Model 

如果需要使用 jwt-auth 作为用户认证,我们需要对app/User模型进行修改,修改后的代码如下:

<?php

namespace App;

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject
{
use Notifiable;

/**
* The attributes that are mass assignable.
*要验证的字段
* @var array
*/
protected $fillable = [
'openid', 'uuid',
];

/**
* 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 [];
}
}

注:此处有一个需要注意的地方如下图 

Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌

7、 配置项详解

文件位置:config/jwt.php,jwt.php中的各种详解

<?php

return [

/*
|--------------------------------------------------------------------------
| JWT Authentication Secret
|--------------------------------------------------------------------------
| 用于加密生成 token 的 secret
*/

'secret' => env('JWT_SECRET'),

/*
|--------------------------------------------------------------------------
| JWT Authentication Keys
|--------------------------------------------------------------------------
| 如果你在 .env 文件中定义了 JWT_SECRET 的随机字符串
| 那么 jwt 将会使用 对称算法 来生成 token
| 如果你没有定有,那么jwt 将会使用如下配置的公钥和私钥来生成 token
*/

'keys' => [

/*
|--------------------------------------------------------------------------
| Public Key
|--------------------------------------------------------------------------
| 公钥
*/

'public' => env('JWT_PUBLIC_KEY'),

/*
|--------------------------------------------------------------------------
| Private Key
|--------------------------------------------------------------------------
| 私钥
*/

'private' => env('JWT_PRIVATE_KEY'),

/*
|--------------------------------------------------------------------------
| Passphrase
|--------------------------------------------------------------------------
| 私钥的密码。 如果没有设置,可以为 null。
*/

'passphrase' => env('JWT_PASSPHRASE'),

],

/*
|--------------------------------------------------------------------------
| JWT time to live
|--------------------------------------------------------------------------
| 指定 access_token 有效的时间长度(以分钟为单位),默认为1小时,您也可以将其设置为空,以
| 产生永不过期的标记
*/

'ttl' => env('JWT_TTL', 60),

/*
|--------------------------------------------------------------------------
| Refresh time to live
|--------------------------------------------------------------------------
| 指定 access_token 可刷新的时间长度(以分钟为单位)。默认的时间为 2 周。
| 大概意思就是如果用户有一个 access_token,那么他可以带着他的 access_token
| 过来领取新的 access_token,直到 2 周的时间后,他便无法继续刷新了,需要重新登录。
*/

'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),

/*
|--------------------------------------------------------------------------
| JWT hashing algorithm
|--------------------------------------------------------------------------
| 指定将用于对令牌进行签名的散列算法。
*/

'algo' => env('JWT_ALGO', 'HS256'),

/*
|--------------------------------------------------------------------------
| Required Claims
|--------------------------------------------------------------------------
| 指定必须存在于任何令牌中的声明。
*/

'required_claims' => [
'iss',
'iat',
'exp',
'nbf',
'sub',
'jti',
],

/*
|--------------------------------------------------------------------------
| Persistent Claims
|--------------------------------------------------------------------------
| 指定在刷新令牌时要保留的声明密钥。
*/

'persistent_claims' => [
// 'foo',
// 'bar',
],

/*
|--------------------------------------------------------------------------
| Blacklist Enabled
|--------------------------------------------------------------------------
| 为了使令牌无效,您必须启用黑名单。如果您不想或不需要此功能,请将其设置为 false。
*/

'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),

/*
| -------------------------------------------------------------------------
| Blacklist Grace Period
| -------------------------------------------------------------------------
| 当多个并发请求使用相同的JWT进行时,
| 由于 access_token 的刷新 ,其中一些可能会失败
| 以秒为单位设置请求时间以防止并发的请求失败。
*/

'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),

/*
|--------------------------------------------------------------------------
| Providers
|--------------------------------------------------------------------------
| 指定整个包中使用的各种提供程序。
*/

'providers' => [

/*
|--------------------------------------------------------------------------
| JWT Provider
|--------------------------------------------------------------------------
| 指定用于创建和解码令牌的提供程序。
*/

'jwt' => Tymon\JWTAuth\Providers\JWT\Namshi::class,

/*
|--------------------------------------------------------------------------
| Authentication Provider
|--------------------------------------------------------------------------
| 指定用于对用户进行身份验证的提供程序。
*/

'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,

/*
|--------------------------------------------------------------------------
| Storage Provider
|--------------------------------------------------------------------------
| 指定用于在黑名单中存储标记的提供程序。
*/

'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,

],

];

8、自定义RefreshToken 中间件

实现效果:提供账号密码前来登录。如果登录成功,那么我会给前端返回一个 token ,设置在 header 中以请求需要用户认证的路由。
如果用户的令牌如果过期了,可以暂时通过此次请求,并在此次请求中刷新该用户的 token,最后在响应头中将新的 token 返回给前端,这样子可以无痛的刷新 token ,用户可以获得一个很良好的体验,所以开始动手写代码。无限刷新默认时间是两周。

php artisan make:middleware RefreshToken

<?php

namespace App\Http\Middleware;

use Closure;
use Auth;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class RefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 检查此次请求中是否带有 token,如果没有则抛出异常。
$this->checkForToken($request);

// 使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException 异常
try {
// 检测用户的登录状态,如果正常则通过
if ($this->auth->parseToken()->authenticate()) {
return $next($request);
}
throw new UnauthorizedHttpException('jwt-auth', '未登录');
} catch (TokenExpiredException $exception) {
// 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
try {
// 刷新用户的 token
$token = $this->auth->refresh();
// 使用一次性登录以保证此次请求的成功
Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
} catch (JWTException $exception) {
// 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
}
}

// 在响应头中返回新的 token
return $this->setAuthenticationHeader($next($request), $token);

}
}

9、注册RefreshToken 中间件

在app/Http/Kernel.php 添加如下代码:

protected $routeMiddleware = [
'refresh' => \App\Http\Middleware\RefreshToken::class,
]

10、更新异常处理的handler

由于我们构建的是 api 服务,所以我们需要更新一下 app/Exceptions/Handler.php 中的 render方法,自定义处理一些异常。

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
//
];

/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];

/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}

/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
// 参数验证错误的异常,我们需要返回 400 的 http code 和一句错误信息
if ($exception instanceof ValidationException) {
return response(['error' => array_first(array_collapse($exception->errors()))], 400);
}
// 用户认证的异常,我们需要返回 401 的 http code 和错误信息
if ($exception instanceof UnauthorizedHttpException) {
return response($exception->getMessage(), 401);
}

return parent::render($request, $exception);
}
}

11、添加新的控制器

创建控制器:

php artisan make:controller AuthController

添加如下代码: 

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Transformers\UserTransformer;

class AuthController extends Controller
{

/**
* Get a JWT token via given credentials.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
// 验证规则,由于业务需求,这里我更改了一下登录的用户名,使用手机号码登录
$rules = [
'email' => [
'required',
'exists:users',
],
'password' => 'required|string|min:6|max:20',
];

// 验证参数,如果验证失败,则会抛出 ValidationException 的异常
$params = $this->validate($request, $rules);

// 使用 Auth 登录用户,如果登录成功,则返回 201 的 code 和 token,如果登录失败则返回
return ($token = Auth::guard('api')->attempt($params))
? response(['token' => 'bearer ' . $token], 201)
: response(['error' => '账号或密码错误'], 400);
}

/**
* 处理用户登出逻辑
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
Auth::guard('api')->logout();

return response(['message' => '退出成功']);
}
}

12、添加路由

在 routes/api.php 文件中,添加路由:

    Route::group(['prefix'=>'auth'],function($router) {
$router->match(['post','get'],'login', 'AuthController@login');
$router->post('logout', 'AuthController@logout');

});

Route::middleware('refresh')->group(function($router) {
$router->get('profile','UserController@profile');
});

 13、在数据库中添加数据

DB::table('users')->insert(
['email' => 'john@example.com', 'password' => bcrypt('123456')]
);

注:此处密码需用函数处理,因为Auth::attempt($params)是使用bcrypt()加密验证的,否则会一直返回false

14、请求接口

Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌

15、请求结果

Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌

注:若邮箱在数据库中不存在,则也会返回false,因为验证规则里面要求的是必须在数据表中存在,自己也可以修改 

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » Laravel 5.5 使用 Jwt-Auth 实现 API 用户认证、刷新令牌
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏