今天咱们来结合实例给你们讲述JWT(Json Web Token)的实战应用,就是如何使用前端Axios与后端PHP实现用户登陆鉴权认证的过程。javascript
axios异步请求:axios-基于Promise的HTTP请求客户端
php-jwt库:https://github.com/firebase/p...
HTML5相关知识
所以在阅读这边文章以前,请先了解以上知识点以及JWT的基本概念,这样你会很快理解咱们这篇文章中的实例代码。php
用户登陆鉴权流程:css
用户使用用户名密码来请求服务器
服务器进行验证用户的信息
服务器经过验证发送给用户一个token
客户端存储token,并在每次请求时附送上这个token值
服务端验证token值,并返回数据
那么如今咱们就按这个流程开始。html
咱们的HTML结构是这样的:一个登陆表单,供用户输入用户名和密码,以及提交按钮;一个是登陆成功后的显示信息。前端
<div id="showpage" style="display: none"> <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> <div id="user" style="display: none"><p>欢迎<strong id="uname"></strong>,您已登陆,<a href="javascript:;" id="logout">退出>></a></p></div>
详细的代码,能够下载demo源码中查看,这里样式咱们使用的是Bootstrap3的经典样式。java
前端Javascript异步请求,咱们使用Axios库,固然你也可使用jQuery的Ajax方法。ios
首先引入axios库:git
<script src="https://cdn.bootcss.com/axios/0.17.1/axios.min.js"></script>
按照流程,
1.提交登陆表单,发送用户名和密码到PHP后端,
2.后端验证成功后,会发送一个token给前端,
3.前端再拿这个token去请求须要用户权限访问,
4.后端验证toen,鉴权,返回相应结果。
下面的js代码实现了1,3两步。github
<script> document.querySelector('#sub-btn').onclick = function() { let username = document.querySelector('#username').value; let password = document.querySelector('#password').value; var params = new URLSearchParams(); params.append('user', username); params.append('pass', password); axios.post( 'user.php?action=login', params ) .then((response) => { if (response.data.result === 'success') { // 本地存储token localStorage.setItem('jwt', response.data.jwt); // 把token加入header里 axios.defaults.headers.common['X-token'] = response.data.jwt; axios.get('user.php').then(function(response) { if (response.data.result === 'success') { document.querySelector('#showpage').style.display = 'none'; document.querySelector('#user').style.display = 'block'; document.querySelector('#uname').innerHTML = response.data.info.data.username; } else { } }); } else { console.log(response.data.msg); } }) .catch(function (error) { console.log(error); }); } </script>
很显然,当登陆成功后,立马使用本地存储token,而后把这个token放在请求头header里,再次去请求后端另外一个用户信息接口,若是成功了就显示用户信息。web
若是要退出登陆,咱们不须要再次去请求后端接口,直接前端清空本地存储就OK了。
document.querySelector('#logout').onclick = function() { localStorage.removeItem('jwt'); document.querySelector('#showpage').style.display = 'block'; document.querySelector('#user').style.display = 'none'; }
登陆成功后,当咱们刷新页面(再次请求须要登陆后才能访问的页面),须要进行判断,判断本地存储中是否有token,若是有token,那就拿去给后端接口验证下token是否合法,若是没问题就显示用户相关信息,若是验证失败,那多是token过去或者伪造的token等缘由。
let jwt = localStorage.getItem('jwt'); if (jwt) { axios.defaults.headers.common['X-token'] = jwt; axios.get('user.php') .then(function (response) { if (response.data.result === 'success') { document.querySelector('#showpage').style.display = 'none'; document.querySelector('#user').style.display = 'block'; document.querySelector('#uname').innerHTML = response.data.info.data.username; } else { document.querySelector('#showpage').style.display = 'block'; console.log(response.data.msg); } }) .catch(function (error) { console.log(error); }); } else { document.querySelector('#showpage').style.display = 'block'; }
后端咱们使用了一个专门的JWT库:php-jwt
使用composer安装php-jwt,接收到登陆用户名和密码后,PHP验证用户名和密码是否正确(实际开发中应该结合数据库,从数据库里拿用户名和密码比对,本实例为了演示只作简单验证),若是用户名和密码准确无误,那么就签发token,在token中,咱们能够定义token的签发者、过时时间等等,并返回给前端。注意在签发token时,咱们须要定义一个密钥,这个密钥是一个私钥,实际应用中是保密的不可告诉别人。
require 'vendor/autoload.php'; use \Firebase\JWT\JWT; define('KEY', '1gHuiop975cdashyex9Ud23ldsvm2Xq'); //密钥 $res['result'] = 'failed'; $action = isset($_GET['action']) ? $_GET['action'] : ''; if ($action == 'login') { if ($_SERVER['REQUEST_METHOD'] == 'POST') { $username = htmlentities($_POST['user']); $password = htmlentities($_POST['pass']); if ($username == 'demo' && $password == 'demo') { //用户名和密码正确,则签发tokon $nowtime = time(); $token = [ 'iss' => 'http://www.helloweba.net', //签发者 'aud' => 'http://www.helloweba.net', //jwt所面向的用户 'iat' => $nowtime, //签发时间 'nbf' => $nowtime + 10, //在什么时间以后该jwt才可用 'exp' => $nowtime + 600, //过时时间-10min 'data' => [ 'userid' => 1, 'username' => $username ] ]; $jwt = JWT::encode($token, KEY); $res['result'] = 'success'; $res['jwt'] = $jwt; } else { $res['msg'] = '用户名或密码错误!'; } } echo json_encode($res); } else { $jwt = isset($_SERVER['HTTP_X_TOKEN']) ? $_SERVER['HTTP_X_TOKEN'] : ''; if (empty($jwt)) { $res['msg'] = 'You do not have permission to access.'; echo json_encode($res); exit; } try { JWT::$leeway = 60; $decoded = JWT::decode($jwt, KEY, ['HS256']); $arr = (array)$decoded; if ($arr['exp'] < time()) { $res['msg'] = '请从新登陆'; } else { $res['result'] = 'success'; $res['info'] = $arr; } } catch(Exception $e) { $res['msg'] = 'Token验证失败,请从新登陆'; } echo json_encode($res); }
用户每次请求都要带上后端签发的token,后端获取请求中的token,PHP中使用$_SERVER['HTTP_X_TOKEN']就能够获取token值。这个X_TOKEN就是在咱们前端的请求header头信息中。
而后PHP拿到这个token后,解密分析token值,返回给前端便可。
以上就是整个JWT的实战应用,咱们能够看到,在用户鉴权的过程当中并无使用Session或者Cookie,服务端无需存储用户会话信息。只用了一个Token串,创建先后端的验证的数据传递,实现了有效的登陆鉴权过程。
在线演示demo:https://www.helloweba.net/dem...