koa ajax JWT签名验证的坑,包括完整连接数据库的操作
前后端分离开发中为了保护API安全,JWT因此产生
用后台管理系统举例说明,我们前端登录发送账号密码给后台,后台进行验证成功后前端便要跳转到登录进去的内容页面,如果不做任何验证,那我们直接访问已登录的链接不就可以进去了吗,因此有了许多验证的方法,JWT便是其中一种,我们前端发送账号密码给后台验证成功后,后台将可直接通过JWT产生一个加密串,然后发送给前端,前端接收到这个加密串后将其存在cooike或者localstorge里,然后每次页面跳转将这个加密串拿出来再发送给后台验证,验证成功就能跳转页面,验证失败将不能跳转,接下来演示JWT的具体实现。
这里是后台Koa部分
//这里是配置的Koa服务器及koa路由,同时引用koa-bodyparser来接收post请求的参数,并且引用jsonwebtoken,koa-jwt模块,这样就
完成了基本配置
const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();
const router = new Router();
const bodyParser = require('koa-bodyparser')
const jwt = require('jsonwebtoken');
const koajwt = require('koa-jwt');
// 连接数据库
const db = {
config: {
host: '这里填写数据库的域名',
user: '数据库账号',
password: '数据库密码',
database: '数据库名',
port: 3306,
multipleStatements: true
// 可以添加 multipleStatements 属性,设置它可以同时执行多条SQL语句 。
},
connection: function (sql, param, cb) {
'use strict';
let myconnect = mysql.createConnection(this.config);
myconnect.connect();
myconnect.query(sql, param, cb);
myconnect.end()
}
};
// 发起后端请求,请求数据库
function promise(sql, arr) {
return new Promise(
(resolve, reject) => {
db.connection(sql, arr, (err, data) => {
if (err == null) {
resolve(data); 将sql语句执行结果返回
}
else {
reject(data);
}
}
)
}
)
}
//这里是设置哪些路由不需要验证JWT,比如有一些请求文章或者公开数据的借口,可以不需要验证JWT,也就是每个人都可以访问的路由,
注意这里你的登录请求的借口是不能验证JWT的,因为你就是要在登录成功后设置JWT,如果先验证了,那肯定是没有JWT然后导致页面错误
app.use(koajwt({
secret: 'my_token' //这是你设置的jwt token名,在下面jwt.sign里设置的
}).unless({
path: ['/user/checkAcc','/user/getArt']
}));
//使用bodyParser模块接收post参数以及使用路由
app.use(bodyParser());
app.use(router.routes());
// 这里是对登录的账号密码进行验证
router.post('/user/checkAcc',async ctx => {
let acc=ctx.request.body.user
let psw=ctx.request.body.psw
let params=[acc,psw]
'use static';
let sql = 'select acc_number from user_table where acc_number=? and acc_psw=?';
await promise(sql,params,[])
.then(function (data) {
console.log(data) //这里的data是查询数据库返回的结果,我这里的data值为 data={acc_id:1,data.acc_num:13100000000},也就是你查询的结果
if (data.length!=0){
const token = jwt.sign({ //这里jwt.sign便是设置加密的内容,我这里是将用户的账号拿到并加密
name: data.acc_number,
_id: data.acc_id
},'my_token', { expiresIn: '2h' }); //expiresln是设置JWT的有效期
ctx.body = { //这里返回给前端参数,data:token里的token就是加密后的内容
code: '1',
data: token,
msg: '登录成功'
}
}
else {ctx.body='0'} //这里处理验证失败返回0,表示没有这个账户
})
.catch(function (data) {
ctx.body='0'
})
});
//下面这个路由是用于验证JWT
router.get('/user/checkjwt',async ctx => {
ctx.body='ok'
});
这里是前端ajax登录部分
//这里用了jquery的方法
function checkAdmin() {
let user = $('.userAdmin').val() //拿到账号
let psw = $('.passwordAdmin').val() //拿到密码
$.ajax({
url: 'https://域名/user/checkAcc',
method: 'post',
data: {acc: user, psw: psw},
success: function (res) {
if (res.code==1){
console.log(res) //如果验证成功,这里将打印出JWT加密的内容
localStorage.setItem('token', res.data) //将jwt的加密内容存到本地localSrorge
location.href='index.html' //验证成功后跳转页面
}
else{alert('账号密码错误')}
}
})
}
这里是前端ajax内部页面验证部分部分
var token
$('body').css('display','none') //可以提前把页面设置为display:none,这样没人能看到你的页面,防止有时候验证延迟,导致可以看到一部分页面内容
$(function () {
token = localStorage.getItem('token') // 从localStroge拿到token
$.ajax({
type: 'GET',
url: 'https://域名/user/checkjwt', // 请求验证jwt的路由
headers: { 'Authorization': 'Bearer '+token}, //这里有个坑点巨坑,在token前要加上'Bearer '这个是表示 token的类型,记住Bearer后面必须有一个空格,必须有,一定别忘了,不然会失败。只需要发送给后台,后台的jwt模块会自己验证,验证失败会报Authorization错误,验证成功将执行你的路由请求操作。
contentType: "application/x-www-form-urlencoded",
success:function (res) {
//因为JWT是先验证再执行之后的路由操作,所以你请求成功JWT验证成功了才会返回参数,这里我后台返回的ok,前面后台代码有写
if (res=="ok"){
$('body').css('display','block') //说明验证成功,验证成功再显示页面
}
},
error:function (error) {
location.href='login.html' //验证失败跳转回登录页面,ok大功告成
}
})
})
部分内容参考https://www.cnblogs.com/linxin/p/9491342.html
如还有什么问题,可在下方留言,我会尽快回复