token(JWT)项目总结

诶,
token是什么?
看看阮一峰怎么说:
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
hahah~分界线
我认为;token就是一把钥匙;通过用户的注册登录获取到两把token钥匙;放在浏览器里;后端给定一个协议;在获取某些信息时需要验证一下前端传过去的这把钥匙;匹配成功获取数据!
钥匙分成2把;一把是短时间token;主要用于获取数据时给给后台做验证的!而另一把长时间token的存在是为了让token更加的严谨;获取数据的钥匙会在短时间内过期,这样通过长时间的token就可以刷新短时间token;从而两者搭配,干活不累~;

so;

  • 前端nodeJS写token(JWT)
  • 实际案例中封装的token

一、前端nodeJS写token(JWT)

JWT(Json Web Tokens)
生成Token的解决方案有许多,常用的一种就是 Json Web Tokens .
JWT标准的Tokens由三部分组成

  1. header:包含token的类型和加密算法
  2. payload:包含token的内容
  3. signature:通过密钥将前两者加密得到最终的token
    这三部分中间使用 " . " 分隔开,并且都会使用Base64编码方式编码,如下
    eyJhbGc6IkpXVCJ9.eyJpc3MiOiJCIsImVzg5NTU0NDUiLCJuYW1lnVlfQ.SwyHTf8AqKYMAJc
    客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。

安装jsw模块

cnpm install jsonwebtoken -S

在js文件中引用jsw模块

var jwt = require(“jsonwebtoken”);

基础生成token

// 要生成token的主题信息【这里可以包含用户的一些相关信息,content需要为一个对象,否则有可能会报错】
var content = { msg: '{"username":"张三"}' }; 
 // 这是加密的key(密钥或私钥) 
 var secretOrPrivateKey = "Odin"
 var token = jwt.sign(content, secretOrPrivateKey, {
    expiresIn: 60 * 1 // 24小时过期,以s作为单位
 });
 console.log("token:"+token);
 var setToken=token;

基础验证token

//获取到token
var tokenVal = "获取的前端传来的token";//rq.body.token || rq.query.token || rq.headers["x-access-token"]; // 可以从body或query或者header中获取token;
tokenVal = setToken;
// 这是加密的key(密钥或私钥) 
var secretOrPrivateKey = "Odin" 
jwt.verify(tokenVal, secretOrPrivateKey, function (err, decode) {
if (err) { // 当token过期,或这是一个伪造的token,或这是无效的token时会触发此逻辑 
console.log(err.message);
} else {
console.log(decode.msg); // {"username":"张三"}
}
})

模块化的封装;导出

//封装tokenObj
var tokenObj = {
	//创建token
    creataToken: function (boxVal, time) { // 内容,时间
        var content = { msg: boxVal }; 
        var secretOrPrivateKey = "Odin"
        var token = jwt.sign(content, secretOrPrivateKey, {
            expiresIn: time // 24小时过期,以s作为单位
        });
        return token;
    },
    //验证token
    checkToken: function (tokenValue,fn) { // token值;导出函数
        var secretOrPrivateKey = "Odin"; //密钥
        jwt.verify(tokenValue,secretOrPrivateKey,function (err,decode) {
            if (err) { 
                console.log(err);
            } else {
                console.log(decode.msg); // {"username":"张三"}
                return fn(decode);//函数导出
            }
        })
    }
}
//模块化的导出
exports.Obj={tokenObj:tokenObj};

前端调用

var token = require("./token.js");
console.log(token);
/*//token打印结果
{ Obj:
   { tokenObj:
      { creataToken: [Function: creataToken],
        checkToken: [Function: checkToken] },
   } }
*/ 
var tokenVal=token.Obj.tokenObj.creataToken("小红",60); // 创建一个token
console.log(tokenVal) // 获取到token(JWT)
token.Obj.tokenObj.checkToken(tokenVal,testOK)  //验证token
function testOK(res){   // 验证成功
    console.log(res);
   	console.log(res.msg); 
}

nodejs实现token运用;

顺序是:
1、本地js发送ajax请求;nodejs向服务器发送数据;服务器响应返回结果;nodejs返回结果和token给本地js;
2、本地js储存token;需要时带上token向nodejs进行验证;nodejs验证成功后返回数据;
html.js

//创建token
 $(".login").click(function(){
          var userName = $(".userName").val();
          var userSex = $(".userSex").val();
          let userBox={
              userName:userName,
              userSex:userSex
          }//获取到数据
          Promise.all([ //发送ajax请求
              $.ajax({
                url: "http://127.0.0.1:8087/userBox/",
                type: "post",
                data:userBox,
                dataType: "json",
              })
            ]).then(
              resolve => {
                resGo(resolve)
              },
              reject => {
                console.log(reject);
              }
            );
      });
    //  登陆成功后获取到token,本地存储
     function resGo(res){
         console.log(res);
         console.log(res[0].tokenVal)
        sessionStorage.setItem("key",res[0].tokenVal);	//本地储存token
     }
 

nodejs(基础设置)

//基础设置
//创建数据库链接(单独部分)
var mysql = require('mysql'); //导入mysql模块
function getcon() {
    //创建数据库相关信息 mysql提供createConnection的链接方法
var connection = mysql.createConnection({
host: '127.0.0.1', //数据库地址
user: 'root', //数据库用户名
password: 'root', //数据库密码
database: 'dowork' //数据库名
});
return connection;//返回结果
}
//导出
module.exports=getcon;
-------------------------------------------------------分割线------------------------------------------------------------------------------------
//导入数据库
var getmySQL = require("./getmySQL");
//导入express模块
var getExpress = require("express");
var toTokenGo = require("../token.js")
//获取express方法
var app = getExpress();
//设置跨域访问(设置在所有的请求前面即可)
app.all("*", function (req, res, next) {
    //设置允许跨域的域名,*代表允许任意域名跨域
    res.header("Access-Control-Allow-Origin", "*");
    //允许的header类型
    res.header("Access-Control-Allow-Headers", "content-type");
    //跨域允许的请求方式 
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    if (req.method == 'OPTIONS')
        res.send(200); //让options尝试请求快速结束
    else
        next();
});
//插入post的body!!
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

nodejs(正式开始!之创建token)
检查一下是否导入sql,express,tokenjs,是否启动数据库

app.post('/userBox', function (req, res) {
    var userName = req.body.userName;
    var userSex = req.body.userSex;
    console.log(userName, userSex)
    var getmySQLCon = getmySQL();
    //启动数据库
    getmySQLCon.connect();
    var sql = `SELECT * FROM userBox WHERE userName = '${userName}' && userSex = ${userSex}`;
    getmySQLCon.query(sql, function (err, result) { //写入数据库
        if (err) {
            console.log("出错了:" + err.message);
            res.send({
                state: false,
                des: "出错了:" + err.message
            });
            getmySQLCon.end();
            return;
        } else {
            if (result.length == 0) {
                res.send({
                    state: true,
                    des: "没有信息哦"
                })
            } else {
                console.log(userName)
                console.log(toTokenGo.Obj.tokenObj);
                //导入模块调用
                var tokenVal = toTokenGo.Obj.tokenObj.creataToken(userName, 60 * 10);
                res.send({ //数据库返回
                    state: true,
                    des: result,
                    tokenVal: tokenVal  //返回token咯~
                })
            }
        }
        getmySQLCon.end();  //关闭数据库
    })
})

通过token验证,获取到数据

     $(".getUser").click(function(){
        //  获得token验证码
         var tokenVal = sessionStorage.getItem("key");
        //  后台交互,通过密钥提升安全性
         Promise.all([
              $.ajax({
                url: "http://127.0.0.1:8087/userALL/",
                type: "post",
                data: {tokenVal:tokenVal}, //注意后台接口文档
                dataType: "json",
              })
            ]).then(
              resolve => {
                console.log(resolve)
              },
              reject => {
                console.log(reject);
              }
            );
     })

nodejs(开始啦!之验证token获取数据)

// token 验证成功后获取数据
app.post('/userALL', function (req, res) {
    var tokenVal = req.body.tokenVal;
  //  console.log(tokenVal); 获取到token进行验证
    toTokenGo.Obj.tokenObj.checkToken(tokenVal, goNext)
    //token验证成功调用
    function goNext(d) {
        console.log(d);
        var getmySQLCon = getmySQL();
        //启动数据库
        getmySQLCon.connect();
        var sql = `SELECT * FROM userBox`;
        getmySQLCon.query(sql, function (err, result) {
            if (err) {
                console.log("出错了:" + err.message);
                res.send({
                    state: false,
                    des: "出错了:" + err.message
                });
                getmySQLCon.end();
                return;
            } else {
                if (result.length == 0) {
                    res.send({
                        state: true,
                        des: "没有信息哦"
                    })
                } else {
                    console.log(toTokenGo);
                    res.send({
                        state: true,
                        des: result,
                    })
                }
            }
            getmySQLCon.end();
        })
    }
})

okε=ε=ε=( ̄▽ ̄)~
在实际中,后端已经写好了token;前端如何是好?

二、实际案例中封装的token

逻辑思路:我们通过按钮事件触发,在向后台登录注册和本地储存长时间和短时间的两种token;短时间token保质期只有5分钟;需要通过长时间的token去做刷新;刷新更新本地短时间token后在回调获取数据

var urlVal = "url基础路径";
// 保存到本地
sessionStorage.setItem("urlVal", "url基础路径");
// !!!!!!!!!!!需要token,并且是formdata格式!!!!!!!!!!!!!!!!!!!!!
//传输数据的give带token myTAjaxGive("get/post", "/url/", 传到数据库的对象, 结果函数的方法名);
function myTAjaxGive(type, url, data, fn) {
    Promise.all([
        $.ajax({
            url: urlVal + url,
            type: type,
            data: data,
            processData: false, //formdata格式要求
            contentType: false,//formdata格式要求
            headers: { "Authorization": "Bearer " + sessionStorage.getItem("tokenValSmall") }//带上头部
        })
    ]).then(
        resolve => { //成功的时候
            // 判定 token 是否过期
            if (resolve[0].code == 200) {
                return fn(resolve);
            } else if (resolve[0].code == 401) { //没有登录的时候
                localStorage.href = "../page/login.html"
            } else if (resolve[0].code == 601) { //5分钟过期了的时候获取新的token
                dataBox = [myTAjaxGive, type, url, data, fn]; //防止异步调用导致本地来不及存上token时的回调函数
                //AjaxGive(type,"url",长时间token,回调函数函数名,回调函数数据)
                AjaxGive("post", "/token/refresh/", { refresh: sessionStorage.getItem("tokenValLong") }, TokenNew, 		dataBox)//我就自动的再去请求下新的
            }
        },
        reject => {
            rejectTime(reject);
        }
    );
}
//!!!!!!!!!!!!!!!!!!!需要token,普通格式!!!!!!!!!!!!!!!!!!!!!
// 传输普通数据
function TAjaxGive(type, url, data, fn) {
    Promise.all([
        $.ajax({
            url: urlVal + url,
            type: type,
            data: data,
            headers: { "Authorization": "Bearer " + sessionStorage.getItem("tokenValSmall") }
        })
    ]).then(
        resolve => { //成功的时候
            // 判定 token 是否过期
            if (resolve[0].code == 200) {
                fn(resolve);
            } else if (resolve[0].code == 401) { //没有登录的时候
                localStorage.href = "../page/login.html"
            } else if (resolve[0].code == 601) { //5分钟过期了的时候获取新的token
                dataBox = [TAjaxGive, type, url, data, fn];
                AjaxGive("post", "/token/refresh/", { refresh: sessionStorage.getItem("tokenValLong") }, TokenNew, dataBox);
            }
        },
        reject => {
            rejectTime(reject);
        }
    );
}

刷新token AjaxGive(type, url, data, fn, fn_data)

//过期刷新token
function AjaxGive(type, url, data, fn, fn_data) {
    Promise.all([
        $.ajax({
            url: urlVal + url,
            type: type,
            data: data
        })
    ]).then(
        resolve => { //成功的时候
            fn(resolve, fn_data);
        },
        reject => {
            rejectTime(reject)
        }
    );
}

回调函数TokengoNew(res, dataBox)

function TokengoNew(res, dataBox) {
    sessionStorage.setItem("tokenValSmall", res[0].msg.access);
    //为了避免异步造成的数据延时
    if (sessionStorage.getItem("tokenValSmall")==res[0].msg.access) {
    	//执行回调
        dataBox[0](dataBox[1], dataBox[2], dataBox[3]);
    } else {
            alert("请求失败")
    }
}

ola~(。・∀・)ノ
其实我在Promise 时出现了异步调用的问题;至今没有很好的解决TT~
token还可以用在7天免登陆;只要后台设置的刷新token(也就是我说的长时间token能够设置到7天;)储存在cookie里面;用户登录的时候刷新就可以了;token的储存肯定是需要加密和隐藏的;后期可以多多改进一下下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值