OBJUI

使用Axios+PHP+JWT实现登录认证

2025-05-26 16:25:13 778
一、什么是JWT JWT(JSON Web Token),顾名思义就是可以在Web上传输的token,这种token是用JSON格式进行format的。它是一个开源标准(RFC7519),定义了一个紧凑的自包含的方式在不同实体之间安全的用JSON格式传输信息。 官网:https://jwt.io/ 二、JWT优缺点 优点:是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。 缺点:对分发出去的Token不可控,续签问题需要谨慎处理好。 三、JWT组成 一个JWT实际上就是一个字符串,它由三部分组成:头部、载荷与签名。 ``` eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxMi4xMi4xMi4yMDIiLCJhdWQiM SwibmJmIjoxNTQzNTcxNDgxLCJleHAiOjE1NDM1Nzg2NzEsImRhdGEiOnsidXNlcmlkI joxLCJ1c2VybmFtZSI6ImFkb.LPKOTnUjSyKTjGVW2553ZuPh9yNRkW8_IuEtXDQc6sI ``` 1、头部(Header) 在header中通常包含了两部分:token类型和采用的加密算法。 ``` { "typ": "JWT", "alg": "HS256" } ``` JWS算法名称描述 | JWS | 算法名称 | 描述 | | ------- | ---------- | -------------------------------- | | HS256 | HMAC256 | HMAC with SHA-256 | | HS384 | HMAC384 | HMAC with SHA-384 | | HS512 | HMAC512 | HMAC with SHA-512 | | RS256 | RSA256 | RSASSA-PKCS1-v1_5 with SHA-256 | | RS384 | RSA384 | RSASSA-PKCS1-v1_5 with SHA-384 | | RS512 | RSA512 | RSASSA-PKCS1-v1_5 with SHA-512 | 对这部分内容使用 Base64 Url编码组成了JWT结构的第一部分。 ``` eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9 ``` 2、载荷Payload 部分 ``` { "sub": "1", "iss": "http://localhost:8000/auth/login", "iat": 1451888119, "exp": 1454516119, "nbf": 1451888119, "jti": "37c107e4609ddbcc9c096ea5ee76c667" } ``` sub: 该JWT所面向的用户 iss: 该JWT的签发者 iat(issued at): 在什么时候签发的token exp(expires): token什么时候过期 nbf(not before):token在此时间之前不能被接收处理 jti:JWT ID为web token提供唯一标识 上述的负载需要经过Base64 Url编码后作为JWT结构的第二部分。 ``` eyJpc3MiOiIxMi4xMi4xMi4yMDIiLCJhdWQiMSwibmJmIjoxNTQzNTcxNDgxLCJleHAiOjE1NDM1Nzg2NzEsImRhdGEiOnsidXNlcmlkIjoxLCJ1c2VybmFtZSI6ImFkb ``` 3、签名 jwt的第三部分是一个签证信息,这个签证信息算法如下: ``` base64UrlEncode(header) + "." + base64UrlEncode(payload)+secret ``` 这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。 例如使用HMAC SHA256算法,那么签名应该使用下列方式创建: ``` Signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) ``` 最终得出jwt的第三部分是: ``` eyJpc3MiOiIxMi4xMi4xMi4yMDIiLCJhdWQiMSwibmJmIjoxNTQzNTcxNDgxLCJleHAiOjE1NDM1Nzg2NzEsImRhdGEiOnsidXNlcmlkIjoxLCJ1c2VybmFtZSI6ImFkb ``` 四、应用场景 1、用于向Web应用传递一些非敏感信息。例如完成加好友、下订单的操作等等。 2、用于设计用户认证和授权系统。 3、实现Web应用的单点登录。 五、示例 安装php-jwt ``` composer require firebase/php-jwt ``` login.php ```php 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); } ``` index.html ```html ``` index.js ```javascript 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); }); } #退出登录 document.querySelector('#logout').onclick = function() { localStorage.removeItem('jwt'); document.querySelector('#showpage').style.display = 'block'; document.querySelector('#user').style.display = 'none'; } #登录后带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'; } ```
更多精彩,请关注公众号

微信公众号

评论:
热门文章: