JWT能夠很好的應用在restful api模式上

什麼是JWT
JWT(JSON Web Token), 顧名思義就是能夠在Web上傳輸的token,這種token是用JSON格式進行format的。 它是一個開源標準(RFC 7519),定義了一個緊湊的自包含的方式在不一樣實體之間安全的用JSON格式傳輸信息。

如今,許多項目模式基本都是前端分離和restful api模式。  所以,傳統的session模式沒法知足認證要求,這時就出現了jwt。  能夠說,restful api模式對於jwt是一個很好的應用場景。

JWT的參數解釋
名稱 解釋
iss (issuer) issuer 請求實體,能夠是發起請求的用戶的信息,也但是jwt的簽發者
sub (Subject) 設置主題,相似於發郵件時的主題
aud (audience) 接收jwt的一方
exp (expire) token過時時間
nbf (not before) 當前時間在nbf設定時間以前,該token沒法使用
iat (issued at) token建立時間
jti (JWT ID) 對當前token設置惟一標示

接下來咱們來看一個例子php

<?php
require_once 'src/JWT.php';
header('Content-type:application/json');
//定義Key
const KEY = 'dasjdkashdwqe1213dsfsn;p';

$user = [
  'uid'=>'dadsa-12312-vsd1s1-fsds',
  'account'=>'daisc',
  'password'=>'123456'
];
$redis = redis();
$action = $_GET['action'];
switch ($action)
{
  case 'login':
    login();
    break;
  case 'info':
    info();
    break;

}
//登錄,寫入驗證token
function login()
{
  global $user;
  $account = $_GET['account'];
  $pwd = $_GET['password'];
  $res = [];
  if($account==$user['account']&&$pwd==$user['password'])
  {
    unset($user['password']);
    $time = time();
    $token = [
      'iss'=>'http://test.cc',//簽發者
      'iat'=>$time,
      'exp'=>$time+60,
      'data'=>$user
    ];
    $jwt = FirebaseJWTJWT::encode($token,KEY);
    $res['code'] = 200;
    $res['message'] = '登陸成功';
    $res['jwt'] = $jwt;

  }
  else
  {
    $res['message']= '用戶名或密碼錯誤';
    $res['code'] = 401;
  }
  exit(json_encode($res));
}

function info()
{
  $jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? false;
  $res['code'] = 200;
  if($jwt)
  {
    $jwt = str_replace('Bearer ','',$jwt);
    if(empty($jwt))
    {
      $res['code'] = 401;
      $res['msg'] = 'You do not have permission to access.';
      exit(json_encode($res));
    }
    try{
      $token = (array) FirebaseJWTJWT::decode($jwt,KEY, ['HS256']);
      if($token['exp']<time())
      {
        $res['code'] = 401;
        $res['msg'] = '登陸超時,請從新登陸';
      }
      $res['data']= $token['data'];
    }catch (Exception $E)
    {
      $res['code'] = 401;
      $res['msg'] = '登陸超時,請從新登陸.';
    }
  }
  else
  {
    $res['code'] = 401;
    $res['msg'] = 'You do not have permission to access.';
  }
  exit(json_encode($res));
}

//鏈接redis
function redis()
{
  $redis = new Redis();
  $redis->connect('127.0.0.1');
  return $redis;
}

這個例子裏面用jwt作了一個簡單的認證。其中用到了一個php-jwt的加密包,連接以下:
https://github.com/firebase/php-jwt 
其中KEY爲定義的私鑰也就是jwt裏面的 sign部分,這個必定要保存好。
而header部分php-jwt包裏面已經幫咱們完成了,加密代碼以下前端

public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
{
  $header = array('typ' => 'JWT''alg' => $alg);
  if ($keyId !== null) {
    $header['kid'] = $keyId;
  }
  if ( isset($head) && is_array($head) ) {
    $header = array_merge($head, $header);
  }
  $segments = array();
  $segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
  $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
  $signing_input = implode('.', $segments);

  $signature = static::sign($signing_input, $key, $alg);
  $segments[] = static::urlsafeB64Encode($signature);

  return implode('.', $segments);
}


能夠看出默認的加密的方式是HS256。這也是說jwt安全的緣由。現階段HS256加密仍是很安全的。
這個包裏面也支持證書加密。

加密解密的過程這個包已經幫咱們完成了。因此咱們只須要定義jwt中的 poyload部分就能夠了。也就是demo裏面的token部分。加密成功會獲得一個加密的Jwt字符串,下次前端在請求api的時候須要攜帶這個jwt字符串做爲認證。
在header頭裏面增長Authorization。在服務端驗證的時候回經過取得這個值來驗證回話的有效。

下面是poyload的一些經常使用配置git

$token  = [
    #非必須。issuer 請求實體,能夠是發起請求的用戶的信息,也但是jwt的簽發者。
    "iss"    => "http://example.org",
    #非必須。issued at。token建立時間,unix時間戳格式
    "iat"    => $_SERVER['REQUEST_TIME'],
    #非必須。expire 指定token的生命週期。unix時間戳格式
    "exp"    => $_SERVER['REQUEST_TIME'] + 7200,
    #非必須。接收該JWT的一方。
    "aud"    => "http://example.com",
    #非必須。該JWT所面向的用戶
    "sub"    => "jrocket@example.com",
    # 非必須。not before。若是當前時間在nbf裏的時間以前,則Token不被接受;通常都會留一些餘地,好比幾分鐘。
    "nbf"    => 1357000000,
    # 非必須。JWT ID。針對當前token的惟一標識
    "jti"    => '222we',
    # 自定義字段
    "GivenName" => "Jonny",
    # 自定義字段
    "name"  => "Rocket",
    # 自定義字段
    "Email"   => "jrocket@example.com",

];


裏面包含的配置能夠自由配置,也能夠本身添加一些其餘的。這些都是網上你們經常使用的,能夠說是一種約定吧。

注意事項
關於jwt的使用大概就是這些。上面的代碼在你使用的時候可能會出現兩個問題:
一、命名空間錯誤
解決:不使用命名空間的話,使用require引入文件。若是使用命名空間出現錯誤,請檢查命名空間的路徑。

二、生成的token是一個對象
解決:(string)$token 將token強轉成stringgithub

相關文章
相關標籤/搜索