JWT是JSON Web Token的缩写,是为了在网络应用环境间传递声明而执行的- -种基于JSON的开放标准((RFC 7519)。JWT本身没有定义任何技术实现,它只是定义了一种基于Token的会话管理的规则,涵盖Token需要包含的标准内容和Token的生成过程,特别适用于分布式站点的单点登录(SSO) 场景。
首先我们需要使用 Composer 来为我们的 TP5.1 项目安装 JWT。在 TP5.1 项目中使用命令行运行以下代码即可自动下载安装:
composer require firebase/php-jwt
装好了之后在 vendor 目录下可以看到 firebase 文件夹
使用 JWT 生成 Token 需要三个参数,分别是负载 (payload)、密匙 (key)、加密算法 (algorithm),其中密匙是由自己规定的,加密算法从源码中选取一种设置,之后接收到传来的 Token 时需要使用此密匙来验证接收到的 Token,负载部分为想要传输的信息,其中有一些字段为官方定义的,但是并不是必需的,除此之外我们还可以定义一些自己的私有字段用来传输额外信息,例如以上实例中将签发时间和生效时间设置为当前时间,Token 过期时间为当前时间的七天后,并加上了自己定义的是否是测试的字段。定义好这些信息后就可以使用 JWT 的静态方法 encode 来生成一个 Token。
开始编码
<?phpnamespace app\Webapi\controller;use Firebase\JWT\JWT;use Firebase\JWT\Key;use think\Controller;class Index extends Controller {private $key = 'sun'; //定义加密所需的密钥(自定义的,这里我用姓名缩写来做密钥)private $algorithm = 'HS256'; //定义加密所需的加密算法(翻看源码得知:支持的算法有'ES384'、'ES256'、'HS256'、'HS384')public function index() {$token = input('post.token'); //接收前端传来的jwt下生成的token$res = $this->verifyToken($token); //验证token合法性if ($res == 'fail') {return json(['code' => 450, 'msg' => 'token验证失败!']);}if ($res == 'redirect') {return json(['code' => 300, 'msg' => 'token过期!']);}#接下来写jwt通过后的业务逻辑// 解析加密值return json(['code' => 200, 'data' => $res]);}/*** 获取jwt生成的token,返回给前端* @return string*/public function getToken() {//jwt载荷(负载) 格式如下非必须$payload = ['iss' => 'anbin', //签发人(自定义该jwt编写人,官方字段:非必需)'iat' => time(), //签发时间(官方字段:非必需)'exp' => (time() + 3600) * 24 * 7, //过期时间(自定义设置7天后过期,官方字段:非必需)'nbf' => time(), //生效时间(在什么时间之后该jwt才可用,官方字段:非必需)'test' => true, //自定义字段'refresh_token'=>"adsfsadfsadf"];return $token = JWT::encode($payload, $this->key, $this->algorithm);}//前端携带token进行验证public function verifyToken($token) {try {//验证通过$result = JWT::decode($token, new Key($this->key, $this->algorithm));return $result;} catch (\Exception $e) {//dump($e->getmessage()); //打印得到错误信息//令牌过期if ($e->getmessage() == 'Expired token') {return 'redirect';}//验证失败return 'fail';}}}
前端可以根据后端设置的 token 有效期时间,把 token 在有效时间内存储起来,而不是每次都请求后端接口来重新获取 token。
JWT拥有基于Token的会话管理方式所拥有的一切优势,不依赖Cookie,使得其可以防止CSRF攻击,也能在禁用Cookie的浏览器环境中正常运行。
而JWT的最大优势是服务端不再需要存储Session,使得服务端认证鉴权业务可以方便扩展,避免存储Session所需要引入的Redis等组件,降低了系统架构复杂度。但这也是JWT最大的劣势,由于有效期存储在Token中,JWT Token-旦签发,就会在有效期内-直可用,无法在服务端废止,当用户进行登出操作,只能依赖客户端删除掉本地存储的JWT Token,如果需要禁用用户,单纯使用JWT就无法做到了。
正在学习Go语言的PHP程序员。