什么是Token?为什么要使用它?
Token实际就是在计算机身份验证中的令牌(临时)的意思。
当前端向后端发起数据请求的时候,后端需要对前端进行身份验证,但是我们又不想每次都输入用户名和密码,这是就需要一个标识来证明自己的身份,这个标识就是token。
基于Token的身份验证流程
- 客户端使用用户名和密码请求登录
- 服务端收到请求,验证登录是否成功
- 验证成功后,服务端会返回一个Token给客户端,反之,返回身份验证失败的信息
- 客户端收到Token后把Token用一种方式存储起来,如( cookie / localstorage / sessionstorage / 其他 )
- 客户端每次发起请求时都会将Token发给服务端
- 服务端收到请求后,验证Token的合法性,合法就返回客户端所需数据,反之,返回验证失败的信息
Token的特点
• 随机性:每次的token都是不一样的
• 不可预测性:没有规律,无法预测
• 时效性: 可以设置token的有效时间
• 无状态、可扩展:由于只是一个算法,扩展起来非常方便
生成Token的解决方案有许多,常用的一种就是 Json Web Tokens(JWT) .
JWT(Json Web Tokens)
JWT标准的Tokens由三部分组成
- header:包含token的类型和加密算法
- payload:包含token的内容
- signature:通过密钥将前两者加密得到最终的token
这三部分中间使用 " . " 分隔开,并且都会使用Base64编码方式编码,如下
eyJhbGc6IkpXVCJ9.eyJpc3MiOiJCIsImVzg5NTU0NDUiLCJuYW1lnVlfQ.SwyHTf8AqKYMAJc
安装jsw模块
cnpm install jsonwebtoken -S
在js文件中引用jsw模块
var jwt = require("jsonwebtoken");
案例(从登陆到发起第一个ajax请求的过程)
将生成token和验证token进行了封装。(token一般设置为15分钟,超时则需要重新登陆)
- 封装好的模块
var jwt = require('jsonwebtoken');
class tokenObj {
creatToken(cont, time) {
var content = { msg: cont };
var secretOrPrivateKey = "blogzl.com";
var token = jwt.sign(content, secretOrPrivateKey, {
expiresIn: time
})
return token;
}
checkToken(token, fn) {
var secretOrPrivateKey = 'blogzl.com' // 这是加密的key(密钥或私钥)
jwt.verify(token, secretOrPrivateKey, function (err, decode) {
if (err) {
console.log(err);
fn(false);
} else {
console.log(decode.msg);
fn(true);
}
})
}
}
- 登陆前端代码
<body>
用户名:<input type="text" name="username" value="张三">
密码:<input type="password" name="password" value="1234">
<button type="button" id="login">登陆</button>
<script src="./js/jquery-3.3.1.js"></script>
<script>
$(function () {
var url = localStorage.getItem("url")
$("#login").on("click", function () {
var username = $('input:text').val();
var password = $('input:password').val();
var data = {
username: username,
password: password
}
$.post(url + "/login", data, function (d) {
if (d.length > 0) {
alert('登陆成功');
// location.href = './index.html'
console.log(d)
console.log(JSON.parse(d))
var dObj = JSON.parse(d);
var token = dObj.token;
sessionStorage.setItem('token', token);
location.href = './index.html'
}
})
})
})
</script>
</body>
- 登陆后端代码
// 登陆
app.post("/login", function (req, res) {
var v = req.body;
var connection = getDBcon();
var sql = "SELECT * FROM users WHERE username=? AND password=?";
console.log(v)
connection.query(sql, [v.username, v.password], function (err, result) {
if (err) {
res.send(err);
return;
} else {
var resObj = {};
if (result.length > 0) {
//查询到了数据,生成token
var myToken = new tokenObj();
var tokenv = myToken.creatToken('hello1', 60 * 15);
resObj.msg = '登陆成功';
resObj.token = tokenv;
res.send(JSON.stringify(resObj))
} else {
resObj.msg = '登陆失败';
res.send(resObj)
}
}
connection.end();
})
})
- 登陆成功后,前端发起的第一个ajax请求(添加)
<body>
<span>返回首页</span>
<div class="main">
<h1>增加客户</h1>
<div>
<div>
<label for="">客户名:</label><input type="text" name="username" id="username"><br>
</div>
<div>
<label for="">性别:</label><input type="text" name="sex" id="sex"><br>
</div>
<div>
<label for="">电话:</label><input type="text" name="tell" id="tell"><br>
</div>
<div>
<label for="">住址:</label><input type="text" name="address" id="address"><br>
</div>
</div>
<button type="button" id="add">添加</button>
</div>
<script src="../js/jquery-3.3.1.js"></script>
<script>
$(function () {
var url = localStorage.getItem("url");
$('#add').on('click', function () {
var username = $('#username').val();
var sex = $('#sex').val();
var tell = $('#tell').val();
var address = $('#address').val();
var token = sessionStorage.token;
console.log(token)
var dataobj = {
username: username,
sex: sex,
tell: tell,
address: address,
token: token
}
$.post(url + '/add', dataobj, function (data) {
var data = JSON.parse(data);
alert(data.msg)
var tokenv = data.token;
sessionStorage.setItem('token', tokenv);
})
})
})
</script>
</body>
- 后端接收到前端的add请求后的处理流程
// 添加
app.post("/add", function (req, res) {
var v = req.body;
//前端传过来的token
var token = v.token;
// 验证前端传过来的token
var myToken = new tokenObj();
myToken.checkToken(token, function (bo) {
if (bo) {
//token验证成功
var connection = getDBcon();
var sql = "INSERT INTO customer(username,sex,tell,address) VALUES(?,?,?,?)";
connection.query(sql, [v.username, v.sex, Number(v.tell), v.address], function (err, result) {
var resobj = {};
if (err) {
res.send(err);
return;
} else {
var myToken = new tokenObj();
var tokenv = myToken.creatToken('hello2', 60 * 15);
resobj.msg = '添加成功';
resobj.token = tokenv;
resobj.result = result;
res.send(JSON.stringify(resobj))
}
connection.end()
})
} else {
//token验证失败
var resobj = {};
resobj.msg = 'token验证失败,请重新登陆';
res.send(JSON.stringify(resobj))
}
})
})