composer : "jwt-auth"
最近在做一个公司的项目,前端使用 Vue.js,后端使用 Laravel 构建 Api 服务,用户认证的包本来是想用 Laravel Passport 的,但是感觉有点麻烦,于是使用了 jwt-auth 。
安装
jwt-auth 最新版本是 1.0.0 rc.1 版本,已经支持了 Laravel 5.5。如果你使用的是 Laravel 5.5 版本,可以使用如下命令安装。根据评论区 @tradzero 兄弟的建议,如果你是 Laravel 5.5 以下版本,也推荐使用最新版本,RC.1 前的版本都存在多用户token认证的安全问题。
$ composer require tymon/jwt-auth 1.0.0-rc.1
配置
添加服务提供商
将下面这行添加至 config/app.php
文件 providers
数组中:
app.php
'providers' => [
...
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]
发布配置文件
在你的 shell 中运行如下命令发布 jwt-auth 的配置文件:
shell
$ php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此命令会在 config
目录下生成一个 jwt.php
配置文件,你可以在此进行自定义配置。
生成密钥
jwt-auth 已经预先定义好了一个 Artisan 命令方便你生成 Secret,你只需要在你的 shell
中运行如下命令即可:
shell
$ php artisan jwt:secret
此命令会在你的 .env
文件中新增一行 JWT_SECRET=secret
。
配置 Auth guard
在 config/auth.php
文件中,你需要将 guards/driver
更新为 jwt
:
auth.php
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
...
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
只有在使用 Laravel 5.2 及以上版本的情况下才能使用。
更改 Model
如果需要使用 jwt-auth 作为用户认证,我们需要对我们的 User
模型进行一点小小的改变,实现一个接口,变更后的 User
模型如下:
User.php
<?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;
// Rest omitted for brevity
/**
* 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 [];
}
}
配置项详解
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,
],
];
自定义认证中间件
先来说明一下我想要达成的效果,我希望用户提供账号密码前来登录。如果登录成功,那么我会给前端颁发一个 access _token ,设置在 header
中以请求需要用户认证的路由。
同时我希望如果用户的令牌如果过期了,可以暂时通过此次请求,并在此次请求中刷新该用户的 access _token,最后在响应头中将新的 access _token 返回给前端,这样子可以无痛的刷新 access _token ,用户可以获得一个很良好的体验,所以开始动手写代码。
执行如下命令以新建一个中间件:
php artisan make:middleware RefreshToken
中间件代码如下:
RefreshToken.php
<?php
namespace App\Http\Middleware;
use Auth;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
// 注意,我们要继承的是 jwt 的 BaseMiddleware
class RefreshToken extends BaseMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
*
* @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);
}
}
设置 Axios 拦截器
我选用的 HTTP 请求套件是 axios。为了达到无痛刷新 token 的效果,我们需要对 axios 定义一个拦截器,用以接收我们刷新的 Token,代码如下:
app.js
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanheagfgf
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24