JWT 在项目中的实际使用
关于JWT 可以参考 JWT 完整使用详解 这里说一下在实际项目中的使用:
laravel 5.5
php7.1
"tymon/jwt-auth": "1.*@rc"
JWT token
的刷新 和 基于 JWT 实现单用户登陆
TOKEN 的刷新
理解
用户登陆后 获取到 tokenA
(这个时候 tokenA
的有效期是60分钟)
通过 tokenA
获取到 tokenB
(这个时候 tokenB
的有效期是60分钟,tokenA
开始进行 60秒的 倒计时,60秒后就会被拉黑)
tokenB
换取 tokenC
(成功后 tokenB
开始进行60秒倒计时,60秒后会被拉黑)
env
配置如下:
JWT_SECRET=jbSn01PbHsFoRzEqHtuOsM3rV3FCsGcI
JWT_BLACKLIST_ENABLED=true # 是否开启toekn黑名单 生产环境需要开启 宽限时间需要开启黑名单(默认是开启的),黑名单保证过期token不可再用,最好打开
JWT_BLACKLIST_GRACE_PERIOD=60 # 设定宽限时间,单位:秒
JWT_REFRESH_TTL=20160 # 刷新时间 单位:分钟
JWT_TTL=60 # 有效时间 单位:分钟
单用户登陆
基于 JWT token
的单用户登陆, 在 token
的载荷配置中做一点手脚即可:
<?php
namespace App\Http\Controllers;
use Auth;
use App\Business\UserBusiness;
use App\Transformers\UserTransformer;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Facades\JWTFactory;
/**
* 用户相关
*
* @Resource("user", uri="/api")
*/
class UserController extends Controller
{
protected $userBusiness;
/**
* UserController constructor.
* @param UserBusiness $userBusiness
*/
public function __construct(UserBusiness $userBusiness)
{
$this->userBusiness = $userBusiness;
}
/**
* 用户登陆
*
* 使用 `username` 和 `password` 进行登陆。
*
* @Post("/login")
* @Versions({"v1"})
* @Transaction({
* @Request({"username": "foo", "password": "bar"}),
* @Response(200, body={"code":1,"time":"2018-08-10 09:32:44","message":"success","data":{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9hcGkuc21hcnR2aWRlby5jb21cL2FwaVwvbG9naW4iLCJpYXQiOjE1MzM4NjQ3NjQsImV4cCI6MTUzMzg2ODM2NCwibmJmIjoxNTMzODY0NzY0LCJqdGkiOiJsZTJObzRLVDZlT0NyVnZCIiwic3ViIjoiZGVkZjYyZTI5MDA0MTFlODgzM2I1NGVlNzVlNTM1MzciLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.OdJlE_pUuttqIxsjKF-FAcZOhMYitS69fh18lPZAYmQ","token_type":"bearer","expires_in":3600}}),
* @Response(200, body=
* {
* "message": "用户不存在",
* "code": 4000,
* "status_code": 500
* }
* )
*
* })
*/
public function login(Request $request)
{
$rules = [
'username' => 'required',
'password' => 'required'
];
$this->_validate($request, $rules);
$spbill_create_ip = $request->header('x-real-ip')?: $request->ip();
iLog('----------spbill_create_ip------------'. $spbill_create_ip);
$username = $request->username;
$password = $request->password;
$login_time = time();
$user = $this->userBusiness->dologin($username,$password,$spbill_create_ip,$login_time);
// Get the token
$factory = JWTFactory::customClaims([
'sub' => $user->guid,
'ip' => $spbill_create_ip,
'login_time' => $login_time
]);
$payload = $factory->make();
$token = JWTAuth::encode($payload);
return $this->_response($this->respondWithToken((string)$token));
}
protected function respondWithToken($token)
{
return [
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => JWTAuth::factory()->getTTL() * 60
];
}
}
<?php
namespace App\Http\Middleware;
use App\Business\ResponseException;
use App\Common\ResponseCode;
use Closure;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
class ClientCheck extends BaseMiddleware
{
/**
* @param $request
* @param Closure $next
* @return mixed
* @throws ResponseException
*/
public function handle($request, Closure $next)
{
$array = $this->auth->payload()->jsonSerialize();
$user = $this->auth->user();
if (key_exists('ip',$array) && key_exists('login_time',$array)) {
if ($array['ip'] != $user->ip || $array['login_time'] != $user->login_at) throw new ResponseException("该账户已在其他设备登陆",ResponseCode::OTHER_CLIENT_LOGIN);
}
return $next($request);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
这是什么注释语法
@lovecn 这是一种高级的注释语法
@lovecn "dingo/api": "2.0.0-alpha1",
我上面的那个写法,已经解决了刷新token了、 只是postman 用的不是很熟。没看到新返回的token.
@echofree313
是的。就是这样的。谢谢。@dividez
甚至可以这样用
求解,你的刷新具体的实现
使用 jwt 的 中间件
@dividez 用jwt.renew是每次请求都对token 进行了刷新,请问题如何只是在过期的时候才进行刷新,否则就不刷新呢
@胸毛仙人
jwt.renew
的刷新, 在response
中的 token 的创建时间 是不会变的,@胸毛仙人 每次都刷新了 token , 只要没有过期 旧 token 都可以用, 将 宽限时间 加多一点就好了,个人觉得,用最新的比较好
@echofree313 能由安政一点的代码吗?