何JWTこと?
JSONウェブトークン(略称JWT)は、最も人気のあるクロスドメイン認証ソリューション。それは三つの部分、以下の例は、以下の具体的な説明から構成されている(JWTは単にラップを使用し、以下を示すために、空の行ない、より便利に見えました)。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjMfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
それはある。「」三つの部分の数、で区切られています。
最初の部分は、ヘッダ情報であり、
{
"alg": "HS256",// 加密的算法
"typ": "JWT"// 加密的方式,填写JWT
}
第二部では、カスタムデータは省略し、自分の状況の定義を見てする必要があり、構成ペイロード、固定6つの部品とカスタムデータです。
'iss' => 'https://www.qqdeveloper.com',// 签发人
'exp' => time() + 86400,// 过期时间(这里的有效期时间为1天)
'sub' => '主题内容',// 主题
'aud' => '受众内容',// 受众
'nbf' => $time,// 生效时间
'iat' => $time,// 签发时间
'jti' => 123,// 编号
第三の部分は、署名(暗号化の最初の2つの部分が来る)です。最初の二つのデータ部分は、このようにデータの漏洩や改ざんを防止し、透明であるので、我々は暗号化が必要です。まず、あなたは鍵(秘密)を指定する必要があります。キーはサーバがユーザに開示することはできません知っていることです。次に、以下の式に従って署名を生成ヘッダ内で指定された署名アルゴリズム(デフォルトHMAC SHA256)を、使用。
第一部分的加密方式(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
最終世代は上の段落の長い文字列です。
JWTを使用する理由
私たちの伝統的な認証モードは、ユーザーの認証と認可のセッションとクッキーに基づいて達成された伝統的な認証モードであるから、これが必要です。図のように、特定のフローパターン。
1.クライアントがサーバにHTTPリクエストを送信します。
それは、クライアントの要求を受け取る2.サーバーは、ユニークなセッションIDを生成し、セッションがサーバーに格納されて生成することが必要である。この特定のセッションの内容SessionIDを保存、デフォルトのファイルストレージは、もちろん、我々は特定の変更することができますされ、そのようなデータベースストレージ等の記憶、。
3.クライアントは、セッションIDごとにリクエストを運ぶ、内部にこのセッションID、クッキーの存在を受信した場合。
4.クライアントからサーバ要求を受信した後、クライアントは、認証と承認に応じてセッションIDを送信します。
ここではまた、あなたがクッキーについての知識内のセッションの前に共有お勧めします。詳細なセッションとクッキー
1.クライアントがサーバにHTTPリクエストを送信します。
2.サーバーはクライアントの要求を受信した後、独自のトークン、生成サーバが生成されたトークンを格納する必要が、それを行う方法のように、セッションクッキーと一貫性のある方法を超えることができます。キャッシュ・データベースはまた、Redisの、memcachedのように、存在してもよいです。
3.サーバがクライアントにトークンを返し、ローカルクライアントヘッダー要求ヘッダーがあるクッキーに格納することができるが存在してもよいが、またのlocalStorageで存在することができます。
4.トークン、認証または認可サーバを運んで、サーバに要求を送信します。
1.クライアントがサーバにHTTPリクエストを送信します。
2.服务端根据jwt的生成规则,生成一个token,并返回给客户端,这里服务端是不需要存储的。
3.客户端在接受到该token时,存在客户端。
4.客户端向服务端发送请求时,服务端对请求的token进行解析,如果发现解析出来的数据和生成的数据是一致的代表是一个合法的token,则进行相应的操作。
基于session和cookie的认证和鉴权模式有什么好与不好的地方呢?总结如下几点:
通过上面几张图,我们也大致可以看得出来,基于session都是需要服务端存储的,而JWT是不需要服务端来存储的。针对以上几点,总结如下:
一、缺点
1.容易遇到跨域问题。不同域名下是无法通过session直接来做到认证和鉴权的。
2.分布式部署的系统,需要使用共享session机制
3.容易出现csrf问题。
二、优点
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变量,访问第二个方法即可解析出具体的数据。