使用Axios+PHP+JWT实现登录认证
1789 2023年04月04日 后端一、什么是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
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
<xmp><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> </xmp>
index.js
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';
}
-
使用Echarts画甘特图
Echarts是一个非常强大的图表库, 下面我们来使用它来画甘特图,
-
go语言怎么连接mysql,并实现增删改查
要使用Go语言连接MySQL,需要使用第三方库。常用的库包括: 这里以go-sql-driver/mysql为 […]
-
beego实现模块化开发
Beego 框架可以通过模块化开发来提高项目的可维护性和可扩展性,可以将一个大型的应用划分为多个模块,每个模块独立维护,有自己的控制器、视图和模型等。
-
Beego实现JWT
Beego是一个基于Go语言的Web框架,实现JWT认证可以通过beego的中间件机制来实现,下面是一个简单的 […]
-
使用Axios+PHP+JWT实现登录认证
JWT(JSON Web Token),顾名思义就是可以在Web上传输的token,这种token是用JSON格式进行format的。它是一个开源标准(RFC7519),定义了一个紧凑的自包含的方式在不同实体之间安全的用JSON格式传输信息。
-
PHP解决雪花算法ID在前端精度丢失的问题
雪花算法(Snowflake)是一种用于生成全局唯一ID的算法,其基本思路是结合时间戳、机器ID、租约ID和序列号生成一个64位的数据,从而保证ID的唯一性。 雪花算法的生成过程如下:
-
虚拟滚动实现页面百万数据滚动
1.概念 虚拟滚动是一种优化长列表性能的技术,它通过按需渲染的方式,只渲染可见部分的列表项,而不是渲染整个列表 […]
-
go实现MD5
在这个示例中,我们使用了Go标准库中的crypto/md5包来计算一个字符串的MD5值。首先,我们将字符串转换 […]
-
Linux服务器Rsync结合inotify同步文件
一、实现效果 服务器A:192.168.161.150 (分布服务器)(rsync客户端+inotify) 服务器B:192.168.161.151 (WEB服务器1)(rsync服务端) 服务器C:192.168.161.152 (WEB服务器2)(rsync服务端) 说明:服务器A有文件更新,自动同步到服务器B和C
-
JavaScript实现滑动验证码
滑动验证码(也叫做滑动拼图验证码)是一种用户交互形式的验证码,通常用于网页或移动应用的登录、注册或敏感操作。其 […]