PHP实现JWT认证方法

PHP实现JWT认证方法

       最近比较空闲,查看了接口安全方面的资料,看到了JWT(JSON Web Token),处于好奇研究看了下,并写了一个代码模拟了这个过程,在这里跟大家分享下,对于什么叫JWT,以及如何使用,在这里我就不重复了,官网写得很仔细了,大家可以访问查看JWT资料

#设置头部
$headers = array(
    "typ" => "JWT",
    "alg" => "HS256"
);
#设置秘钥
$key = '123456';

#############################demo#############################

$payload = array(
    "iss" => "admin",                                   //jwt签发者
    'sub' => 'user',                                    //jwt所面向的用户
    'aud' => 'John Doe',                                //接收jwt的一方
    'exp' => time() + 60 * 60,                          //jwt的过期时间,这个过期时间必须要大于签发时间
    'iat' => time(),                                    //jwt的签发时间
    'jti' => md5(uniqid('JWT') . time()),  //Token      //token
);

#生成token
$token = getToken($payload, $headers, $key);
echo "签发的签名" . $token;
#检验token
$getPayload = verifyToken($token, $key);
var_dump($getPayload);

#############################生成token#############################

/**
 * 拼接生成token
 * @param $payload
 * @param $headers
 * @param $key
 * @return bool|string
 */
function getToken($payload, $headers, $key)
{
    if (is_array($payload)) {
        $base64header = base64UrlEncode(json_encode($headers, JSON_UNESCAPED_UNICODE));
        $base64payload = base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
        $token = $base64header . '.' . $base64payload . '.' . signature($base64header . '.' . $base64payload, $key, $headers['alg']);
        return $token;
    } else {
        return false;
    }
}

/**
 * 生成签名
 * @param $input
 * @param $key
 * @param string $alg
 * @return mixed
 */
function signature($input, $key, $alg = 'HS256')
{
    $alg_config = array(
        'HS256' => 'sha256'
    );
    return base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true));
}

#############################解析token#############################

/**
 * 验证签名
 * @param $Token
 * @param string $key
 * @return bool|mixed
 */
function verifyToken($Token, $key = "")
{
    $tokens = explode('.', $Token);
    if (count($tokens) != 3)
        return false;

    list($base64header, $base64payload, $sign) = $tokens;

    //获取jwt算法
    $base64DecodeHeader = json_decode(base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
    if (empty($base64DecodeHeader['alg']))
        return false;

    //签名验证
    if (signature($base64header . '.' . $base64payload, $key, $base64DecodeHeader['alg']) !== $sign)
        return false;

    $payload = json_decode(base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

    //签发时间大于当前服务器时间验证失败
    if (isset($payload['iat']) && $payload['iat'] > time())
        return false;

    //过期时间小宇当前服务器时间验证失败
    if (isset($payload['exp']) && $payload['exp'] < time())
        return false;

    //该nbf时间之前不接收处理该Token
    if (isset($payload['nbf']) && $payload['nbf'] > time())
        return false;

    return $payload;
}

#############################公共方法#############################

/**
 * base64链接编码
 * @param $input
 * @return mixed
 */
function base64UrlEncode($input)
{
    return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}

/**
 * base64链接解码
 * @param $input
 * @return bool|string
 */
function base64UrlDecode($input)
{
    $remainder = strlen($input) % 4;
    if ($remainder) {
        $addlen = 4 - $remainder;
        $input .= str_repeat('=', $addlen);
    }
    return base64_decode(strtr($input, '-_', '+/'));
}

       上面就是token的签发以及鉴定的过程,大家可以参考看看。