JWT生成Token做登录校验 一、JWT的优点 二、使用JWT进行用户登录鉴权的流程 三、php-jwt库下载地址 三、简单示例

1、服务端不需要保存传统会话信息,没有跨域传输问题,减小服务器开销。

2、jwt构成简单,占用很少的字节,便于传输。

3、json格式通用,不同语言之间都可以使用。

二、使用JWT进行用户登录鉴权的流程

① 用户使用用户名密码来请求服务器

② 服务器进行验证用户的信息

③ 服务器通过验证发送给用户一个token

④ 客户端存储token,并在每次请求时附送上这个token值

⑤ 服务端验证token值,并返回数据

三、php-jwt库下载地址

1、通过composer下载:

composer require firebase/php-jwt

2、github下载地址:https://github.com/firebase/php-jwt

3、百度云下载地址:https://pan.baidu.com/s/1lpyz8oKf_CM-kOi7MGVoPg

提取码:wyq0

三、简单示例

1、登录页面代码:login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="showpage">
    <div class="form-group">
        <label for="username">用户名</label>
        <input type="text" class="form-control" id="username" placeholder="请输入用户名">
    </div>
    <div class="form-group">
        <label for="password">密码</label>
        <input type="password" class="form-control" id="password" placeholder="请输入密码">
    </div>
    <button type="submit" id="sub-btn" class="btn btn-default">登录</button>

    <br/>
    <p class="bg-warning" style="padding: 10px;">演示用户名和密码都是<code>demo</code></p>
</div>
</body>
</html>

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
    $('#sub-btn').on('click',function (e) {
        $.ajax({
            type: 'post',
            url: './user.php?action=login',
            data: {
                username:$('#username').val(),
                password:$('#password').val(),
            },
            dataType:'json',
            success: function (data, status, xhr) {
                alert(data.msg);
                if(data.code==200){
                    //将jwt存储到本地
                    var jwt = xhr.getResponseHeader('Authorization');
                    localStorage.setItem("jwt", jwt);
                    //跳转登录成功的页面
                    window.location.href="./user.html";
                }
            }
        });
    });
</script>

2、登录成功后页面代码:user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>你已成功登陆</h3>
</body>
</html>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
    $.ajax({
        type: 'post',
        url: './user.php',
        headers: {
            'Authorization': localStorage.getItem("jwt")
        },
        data: {},
        async: true,
        dataType: 'json',
        success: function (data, status, xhr) {
            if(data.code!=200){
                //jwt验证失败
            }
            //如果响应头接收到了Authorization,则将本地jwt更新
            if (xhr.getResponseHeader('Authorization')) {
                localStorage.setItem("jwt", jwt);
            }
        },
        error: function () {
            alert('error');
        }
    });
</script>

3、后端PHP代码:user.php

<?php
/*
 使用composer安装php-jwt,接收到登录用户名和密码后,PHP验证用户名和密码是否正确
(实际开发中应该结合数据库,从数据库里拿用户名和密码比对,本实例为了演示只做简单验证),
如果用户名和密码准确无误,那么就签发token,在token中,我们可以定义token的签发者
、过期时间等等,并返回给前端。注意在签发token时,我们需要定义一个密钥,这个密钥是一个私钥,
实际应用中是保密的不可告诉别人。
 * */
require_once './php-jwt-master/src/JWT.php';

use FirebaseJWTJWT;

define('KEY', '1gHuiop975cdashyex9Ud23ldsvm2Xq'); //密钥

$action = isset($_GET['action']) ? $_GET['action'] : '';
if ($action == 'login') {
    if ($_SERVER['REQUEST_METHOD'] == 'POST') {
        $username = htmlentities($_POST['username']);
        $password = htmlentities($_POST['password']);
        $data     = ['userid' => 1, 'username' => $username];

        if ($username == 'demo' && $password == 'demo') { //用户名和密码正确,则签发tokon
            $nowtime = time();
            $token   = [
                'iss'  => 'http://www.helloweba.net', //签发者
                'aud'  => $_SERVER['REMOTE_ADDR'], //jwt所面向的用户
                'iat'  => $nowtime, //签发时间
                'exp'  => $nowtime + 600, //过期时间-10min
                'data' => $data
            ];
            $jwt     = JWT::encode($token, KEY);
            header("Authorization:$jwt");
            $res = array('code' => 200, 'msg' => '登录成功', 'data' => $data);
        } else {
            $res = array('code' => 300, 'msg' => '登录失败');
        }
    }
    die(json_encode($res));

} else {
    $jwt = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : '';
    if (empty($jwt)) {
        $res = array('code' => 301, 'msg' => 'You do not have permission to access.');
        die(json_encode($res));
    }
    try {
        JWT::$leeway = 60;//当前时间减去60,把时间留点余地
        $token       = JWT::decode($jwt, KEY, ['HS256']); //HS256方式,这里要和签发的时候对应
    } catch (Exception $exception) {
        $res = array('code' => 302, 'msg' => $exception->getMessage());
        die(json_encode($res));
    }


    // 疑似窃取用户Token攻击行为:请求的客户端ip已经改变, 拒绝请求
    if ($token->aud !== $_SERVER['REMOTE_ADDR']) {
        $res['msg'] = "请求的客户端ip已经改变, 拒绝请求";
    }

    // token过了有效期, 但是在回旋时间内, 静默更新用户token
    if ($token->exp < time()) {
        $token        = (array)$token;
        $nowtime      = time();
        $token['iat'] = $nowtime; //签发时间
        $token['exp'] = $nowtime + 600; //过期时间-10min;

        $jwt = JWT::encode($token, KEY);
        header("Authorization:$jwt");
    }

    $res = array('code' => 200, 'msg' => 'success');
    die(json_encode($res));

}