能直接在hyperf框架中使用jwt的组件. 请看下下面的文档~,3.0.x不兼容2.0.x,具体请切换分支查看
1、由于
Hyperf可以升级
1.1版本,如果你用
1.1版本,请需要修改
jwt-auth的
composer.json文件,把依赖
Hyperf的组件版本全部改为
~1.1.0或者使用
jwt-auth的
^2.0.1版本,这个版本是针对
Hyperf的
1.1版本的
"hyperf/utils": "required hyperf/utils ~2.0.0 OR required hyperf/utils ~1.1.0", "hyperf/cache": "required hyperf/cache ~2.0.0 OR required hyperf/cache ~1.1.0", "hyperf/command": "required hyperf/command ~2.0.0 OR required hyperf/command ~1.1.0", "hyperf/config": "required hyperf/config ~2.0.0 OR required hyperf/config ~1.1.0", "hyperf/di": "required hyperf/di ~2.0.0 OR required hyperf/di ~1.1.0"为什么要这样做?因为发现1.1.x和2.0.x的升级不影响该包的代码
composer require phper666/jwt-auth:~2.0.1 composer require hyperf/utils:~1.0.1 composer require hyperf/cache:~1.0.1 composer require hyperf/command:~1.0.1 composer require hyperf/config:~1.0.1 composer require hyperf/di:~1.0.1如果你使用hyperf 2.0.x,你可以:
composer require phper666/jwt-auth:~2.0.1 composer require hyperf/utils:~2.0.0 composer require hyperf/cache:~2.0.0 composer require hyperf/command:~2.0.0 composer require hyperf/config:~2.0.0 composer require hyperf/di:~2.0.0
jwt-auth支持单点登录、多点登录、支持注销 token(token会失效)、支持刷新 token单点登录:只会有一个 token 生效,一旦刷新 token ,前面生成的 token 都会失效,一般以用户 id 来做区分
多点登录:token 不做限制,一旦刷新 token ,则当前 token 会失效
注意:使用单点登录或者多点登录时,必须要开启黑名单,并且使用
Hyperf的缓存(建议使用redis缓存)。如果不开启黑名单,无法使 token 失效,生成的 token 会在有效时间内都可以使用(未更换证书或者 secret )。单点登录原理:
JWT有七个默认字段供选择。单点登录主要用到 jti 默认字段,jti字段的值默认为用户 id。当生成 token 时,getToken方法有一个$isInsertSsoBlack参数来控制是否会把前面生成的 token 都失效,默认是失效的,如果想不失效,设置为false即可。但是如果是调用refreshToken来刷新 token 或者调用logout注销token,默认前面生成的 token 都会失效。
jwt 的生成的 token 加入黑名单时,会把用户 id 作为缓存的键,当前时间作为值,配置文件中的blacklist_cache_ttl作为缓存的失效时间。每次生成 token 或者刷新 token 时,会先从 token 中拿到签发时间和jti值找到对应的缓存拿到时间,拿到时间后跟 token 的签发时间对比,如果签发时间小于等于拿到的时间值,则 token 判断为失效的。(jti在单点登录中,存的值是用户 id)多点登录原理:多点登录跟单点登录差不多,唯一不同的是jti的值不是用户 id,而是一个唯一字符串,每次调用
refreshToken来刷新token或者调用logout注销 token 会默认把请求头中的 token 加入到黑名单,而不会影响到别的 tokentoken 不做限制原理:token 不做限制,在 token 有效的时间内都能使用,你只要把配置文件中的
blacklist_enabled设置为false即可,即为关闭黑名单功能
如果你使用
Hyperf 1.0.x版本,则shell composer require phper666/jwt-auth:~1.0.1如果你使用
Hyperf 1.1.x版本,则shell composer require phper666/jwt-auth:~2.0.1
php bin/hyperf.php jwt:publish --config
去配置
config/autoload/jwt.php文件或者在配置文件
.env里配置 ```shell
JWT_SECRET=hyperf
JWT_TTL=60 ``
更多的配置请到config/autoload/jwt.php` 查看
在
config/autoload/middlewaress.php配置文件中加入
jwt验证中间件,所有的路由都会进行
token的验证,例如:
shell [ Phper666\JwtAuth\Middleware\JwtAuthMiddleware:class ], ];
在
config/routes.php文件中,想要验证的路由加入
jwt验证中间件即可,例如: ```shell <?php
Router::addGroup('/v1', function () { Router::get('/data', 'App\Controller\[email protected]'); }, ['middleware' => [Phper666\JwtAuth\Middleware\JwtAuthMiddleware::class]]); ```
请看官方文档:https://doc.hyperf.io/#/zh/middleware/middleware 在你想要验证的地方加入
jwt 验证中间件即可。
request->input('username'); $password = $this->request->input('password'); if ($username && $password) { $userData = [ 'uid' => 1, 'username' => 'xx', ]; $token = (string)$jwt->getToken($userData); return $this->response->json(['code' => 0, 'msg' => '获取token成功', 'data' => ['token' => $token]]); }return $this->response->json(['code' => 0, 'msg' => '登录失败', 'data' => []]); } # http头部必须携带token才能访问的路由 public function getData() { return $this->response->json(['code' => 0, 'msg' => 'success', 'data' => ['a' => 1]]); }
}
注意:暂时不支持传入用户对象获取 token,后期会支持
获取数据Router::addGroup('/v1', function () { Router::get('/data', 'App\Controller\[email protected]'); }, ['middleware' => [Phper666\JwtAuth\Middleware\JwtAuthMiddleware::class]]);
在需要鉴权的接口,请求该接口时在
HTTP头部加入
shell Authorization Bearer token
{ "code": 0, "msg": "获取token成功", "data": { "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1NjQ3MzgyNTgsIm5iZiI6MTU2NDczODI1OCwiZXhwIjoxNTY0NzM4MzE4LCJ1aWQiOjEsInVzZXJuYW1lIjoieHgifQ.CJL1rOqRmrKjFpYalY6Wu7JBH6vkbysfvOf-TMQgonQ" } }
{ "code": 0, "msg": "success", "data": { "a": 1 } }
namespace App\Controller;use Hyperf\Di\Annotation\Inject; use Hyperf\HttpServer\Annotation\AutoController; use \Phper666\JwtAuth\Jwt;
/**
@AutoController()
Class IndexController
@package App\Controller
/ class IndexController extends AbstractController { /**
@Inject()
@var Jwt
/ protected $jwt;
public function login() { $username = $this->request->input('username'); $password = $this->request->input('password'); if ($username && $password) {
$userData = [
'uid' => 1, // 如果使用单点登录,必须存在配置文件中的sso_key的值,一般设置为用户的id
'username' => 'xx',
];
$token = $this->jwt->getToken($userData);
$data = [
'code' => 0,
'msg' => 'success',
'data' => [
'token' => (string)$token,
'exp' => $this->jwt->getTTL(),
]
];
return $this->response->json($data);
} return $this->response->json(['code' => 0, 'msg' => '登录失败', 'data' => []]); }
public function refreshToken() { $token = $this->jwt->refreshToken(); $data = [
'code' => 0,
'msg' => 'success',
'data' => [
'token' => (string)$token,
'exp' => $this->jwt->getTTL(),
]
]; return $this->response->json($data); }
public function logout() { $this->jwt->logout(); return true; }
public function getData() { $data = [
'code' => 0,
'msg' => 'success',
'data' => [
'cache_time' => $this->jwt->getTokenDynamicCacheTime() // 获取token的有效时间,动态的
]
]; return $this->response->json($data); }
public function index() { $user = $this->request->input('user', 'Hyperf'); $method = $this->request->getMethod();
return [
'method' => $method,
'message' => "Hello {$user}.",
]; } }
提供了一个方法
getParserData来获取解析后的 token 数据。 例如:
$this->jwt->getParserData()
目前
jwt抛出的异常目前有两种类型Phper666\JwtAuth\Exception\TokenValidException和Phper666\JwtAuth\Exception\JWTException,TokenValidException异常为 token 验证失败的异常,会抛出401,JWTException异常会抛出400,最好你们自己在项目异常重新返回错误信息