JWT是什么?php
JSON Web Token(缩写 JWT)是目前最流行的<font color='red'>跨域</font>认证解决方案。它是有三部分组成,示例以下,具体的讲解以下(jwt是不会有空行的,下面只是为了显示,便使用了换行看着比较方便)。redis
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjMfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
它是由一个"."号隔开、三部分组成。 第一部分是header信息,算法
{ "alg": "HS256",// 加密的算法 "typ": "JWT"// 加密的方式,填写JWT }
第二部分是Payload,有固定的六个部分和自定义数据组成,自定义数据看本身的状况须要来定义,是能够省去的。shell
'iss' => 'https://www.qqdeveloper.com',// 签发人 'exp' => time() + 86400,// 过时时间(这里的有效期时间为1天) 'sub' => '主题内容',// 主题 'aud' => '受众内容',// 受众 'nbf' => $time,// 生效时间 'iat' => $time,// 签发时间 'jti' => 123,// 编号
第三部分是Signature(是对前两部分加密得来的)。因为前两部分是公开透明的数据,所以防止数据的篡改和泄露,咱们须要加密处理。首先,须要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。而后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。数据库
第一部分的加密方式( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
最终生成的就是上面很长的一段字符串了。编程
为何会使用JWTjson
这就须要从咱们传统的认证模式来讲了,传统的认证模式是基于session和cookie来实现用户的认证和鉴权。具体的流程模式以下图。跨域
<center>(图一)Session与Cookie认证与鉴权</center> 1.客户端向服务端发送一个http请求。缓存
2.服务端在收到客户端的请求时,生成一个惟一的sessionid,<font color='red'>这里须要将该生成的session存储在服务端</font>,这个sessionid存储具体的session内容,默认的是文件存储,固然咱们能够修改具体的存储方式,例如数据库存储。 3.客户端在接受到这个sessionid时,存在cookie里面,每次请求时携带该sessionid。 4.服务端在接收到客户端的请求以后,根据客户端发送的sessionid来进行认证与受权。 这里也推荐一下本身以前分享的一篇有关session于cookie的知识点。session与cookie详解 安全
<center>(图二)传统的token受权</center> 1.客户端向服务端发送一个http请求。
2.服务端在收到客户端的请求以后,生成一个惟一token,<font color='red'>这里须要将该生成的token存储在服务端</font>,至于怎么存,能够和上面session与cookie的方式一致。也能够存在缓存数据库中,如redis,memcached。 3.服务端将该token返回给客户端,客户端存在本地,能够存请求头header中,也能够存在cookie中,同时也能够存在localstorage中。 4.向服务端发送请求时,携带该token,服务端进行认证或者受权。
<center>(图三)JWT认证模式</center> 1.客户端向服务端发送一个http请求。
2.服务端根据jwt的生成规则,生成一个token,并返回给客户端,<font color='red'>这里服务端是不须要存储的</font>。 3.客户端在接受到该token时,存在客户端。 4.客户端向服务端发送请求时,服务端对请求的token进行解析,若是发现解析出来的数据和生成的数据是一致的表明是一个合法的token,则进行相应的操做。
基于session和cookie的认证和鉴权模式有什么好与很差的地方呢?总结以下几点:
经过上面几张图,咱们也大体能够看得出来,基于session都是须要服务端存储的,而JWT是不须要服务端来存储的。针对以上几点,总结以下: 1、缺点 1.容易遇到跨域问题。不一样域名下是没法经过session直接来作到认证和鉴权的。 2.分布式部署的系统,须要使用共享session机制 3.容易出现csrf问题。
2、优势 1.方便灵活,服务器端直接建立一个sessionid,下发给客户端,客户端请求携带sessionid便可。 2.session存储在服务端,更加安全。 3.便于服务端清除session,让用户从新受权一次。
JWT与session有什么区别呢?
JWT是基于客户端存储的一种认证方式,然而session是基于服务端存储的一种认证方式。JWT虽然不用服务端存储了,也能够避免跨域、csrf等状况。但也存在以下几个不太好的地方。 1.没法清除认证token。因为JWT生成的token都是存储在客户端的,不能有服务端去主动清除,只有直到失效时间到了才能清除。除非服务端的逻辑作了改变。 2.存储在客户端,相对服务端,安全性更低一些。当JWT生成的token被破解,咱们不便于清除该token。
如何使用JWT
这里推荐使用GitHub上面人家封装好的包,这里我使用的是firebase/php-jwt,在项目中直接使用便可安装成功。
composer require firebase/php-jwt
接下来建立一个控制器,我这里使用的ThinkPHP5.1的框架
use think\Controller; use Firebase\JWT\JWT; class Test extends Controller { private $key = 'jwtKey'; // 生成JWT public function createJwt() { $time = time(); $key = $this->key; $token = [ 'iss' => 'https://www.qqdeveloper.com',// 签发人 'exp' => $time + 86400,// 过时时间(这里的有效期时间为1天) 'sub' => '主题内容',// 主题 'aud' => '受众内容',// 受众 'nbf' => $time,// 生效时间 'iat' => $time,// 签发时间 'jti' => 123,// 编号 // 额外自定义的数据 'data' => [ 'userName' => '编程浪子走四方' ]]; // 调用生成加密方法('Payloadn内容','加密的键',['加密算法'],['加密的能够'],['JWT的header头']) $jwt = JWT::encode($token, $key); return json(['data' => $jwt]); } // 解析JWT public function analysisJwt() { try { $key = $this->key; $jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImV4cCI6MTU2ODA5NjE4MCwic3ViIjoiXHU0ZTNiXHU5ODk4XHU1MTg1XHU1YmI5IiwiYXVkIjoiXHU1M2Q3XHU0ZjE3XHU1MTg1XHU1YmI5IiwibmJmIjoxNTY4MDA5NzgwLCJpYXQiOjE1NjgwMDk3ODAsImp0aSI6MTIzLCJkYXRhIjp7InVzZXJOYW1lIjoiXHU3ZjE2XHU3YTBiXHU2ZDZhXHU1YjUwXHU4ZDcwXHU1NmRiXHU2NWI5In19.kHb_9Np0zjE25YE9czUEGvmFPYtqMJT9tuZzJTuMZl0'; // 调用解密方法('JWT内容','解密的键,和加密时的加密键一直','加密算法') $decoded = JWT::decode($jwt, $key, array('HS256')); return json(['message' => $decoded]); } catch (\Exception $exception) { return json(['message' => $exception->getMessage()]); } } }
经过访问第一个方法,能够生成下图一段字符串 咱们将上图中的字符串复制到第二图中的$jwt变量,访问第二个方法便可解析出具体的数据。