token的理解和代码,token是什么?

文章讲述了面试中关于接口文档安全的问题,面试官实际上是考察对身份鉴权的理解。介绍了JWT在前后端分离项目中的使用,包括登录验证、token生成与验证流程,以及node和MySQL的配合。
摘要由CSDN通过智能技术生成
面试场景:

以前有个学生去面试,公司问他,如果你们公司的接口文档被你的亲戚看到了,会怎么样?会导致什么问题,为了防止这个问题,需要用什么来解决?这个根据学生回忆的写的。

学生当场懵逼。我的亲戚……,我的亲戚看不懂啊……%¥#?~%¥#?~………………,我的亲戚也不懂程序啊%¥#?~%¥#?~%¥#?~………………

其实,面试官想问的意思是,如果一个公司的接口文档被别人(懂程序,懂前端的人)看见,他如果写个代码发送请求,是不是可以把数据库中的数据拿到,如何防止这种情况。

这个其实就是一个身份,鉴权的问题。现在前后端分离开发后,一般都用token解决。

本文章后端使用node+mySQL,和 JWT(JSON WEB TOKEN)。

一、token的思路

1、客户端使用用户名和密码请求登录接口(前端做)

2、服务端收到请求,去验证用户名与密码 (后端做)

3、验证成功后,服务端会签发(产生)一个 Token(加了密的字符串),再把这个 Token 发送给客户端(后端做)

4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage (sessionStorage)里(前端)

5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token(前端)

6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

二、代码:

1、登录时,产生token。
1)、前端代码:

输入用户名和密码,发送请求。登录成功后,把后端响应的token保存起来。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
</head>
<body>
    <div>
        <h1>登录页面</h1>
        <p>
            手机号:
            *<input type="text" id="userphone">
        </p>
        <p>
            密码:
            <input type="password" id="userpass">
        </p>
        <p>
            <input type="button" value="登录" id="btnLogin">
            <span id="errMsg"></span>
        </p>
    </div>
</body>
</html>
<script src="./js/jquery.js"></script>
<script src="./js/ajaxTools.js"></script>//这个是自己封装ajax库
<script src="./js/cookieTools.js"></script>//这个是自己封装的cookie库。
<script>
​
function loginCheck(){
    // 1、非空判断
​
    // 2、登录的前后端交互(调用的自己封装的ajax库的函数)
    ajaxUsePromise02({
        url:"http://10.12.156.16:9000/login",
        method:"post",
        data:`loginname=${$("#userphone").val()}&password=${$("#userpass").val()}`
    }).then(res=>{
        if(res.code=="200"){
            //保存用户名(调用的自己封装的cookie库的函数)
            saveCookie("userphone",$("#userphone").val(),7);
            //保存token
            sessionStorage.setItem("token",res.data.token);
            location.href="index.html";
        }else{
            $("#errMsg").html("亲,账户号或者密码不对").css({color:"red"});
        }
    })
}
​
window.onload = function(){
    $("#btnLogin").on("click",loginCheck)
    // document.getElementById("btnLogin").onclick = loginCheck;
}
​
</script>

2)、后端代码:

接收前端传来的用户名和密码。去数据库中验证,验证通过后,产生token,响应给前端。

var express = require("express");
var router = express.Router();
var mysql = require("mysql");
const jwt = require("jsonwebtoken");
​
router.post("/", function (req, res, next) {
  // 1、接收前端的数据
  let loginname = req.body.loginname;
  let password = req.body.password;
​
  // 2、后端逻辑
  //  1)、连接数据库
  var connection = mysql.createConnection({
    host: "localhost", //主机名
    user: "root",
    password: "root",
    database: "db2308", //库名
  });
​
  connection.connect();
​
  // 2)、执行sql语句
  let sqlStr = `select * from users where tel='${loginname}' and password='${password}'`;
  connection.query(sqlStr, function (error, results, fields) {
    if (error) {
      res.json({
        code: "0",
        msg: "登录失败,连接数据库出错!",
      });
      return;
    }
    // 3、响应
    if (results.length == 1) {
      //产生token
      let token = jwt.sign({username:loginname,userpass:password}, "who are you?");
      res.json({
        code: "200",
        msg: "登录成功!",
        data:{
          loginname:loginname,
          password:password,
          token:token//把token响应给前端
        }
      })
    }else{
      res.json({
        code: "10011",
        msg: "登录失败,用户名或者密码不对!",
      })
    }
  });
  // 3)、关闭数据库
  connection.end();
});
​
module.exports = router;
​

2、再次发送请求时,携带token
1)、前端代码:

token一般都携带在请求头里。

 // 发送请求,从后端获取商品数据
ajaxUsePromise02({
    url: `${baseurl}/getGoodslist`,
    data: data,
    headers: {
        token: sessionStorage.getItem("token");// 把token携带在头部
    }
})

2)、后端代码:

先从请求头里拿到token。然后,验证token是否正确,如果正确,才给前端响应数据。

var express = require("express");
const connection = require("../db/conn");
var router = express.Router();
​
//专门定义一个验证token的函数。
const tokenVerify= function (req, res, success, fail) {
  // 还需要拿token
  let token = req.query.token;
  console.log("token", token);
​
  try {
    //这句话是验证token的。
    let decoded = jwt.verify(token,  "who are you?");
    console.log("decoded", decoded);
​
    //  1)、连接数据库
    var connection = mysql.createConnection({
      host: "localhost", //主机名
      user: "root",
      password: "root",
      database: "db2308", //库名
      port: 3306,
    });
    connection.connect();
​
    // 2)、执行sql语句
    let sqlStr = `select * from users where tel='${decoded.username}' and password='${decoded.userpass}'`;
    console.log("sqlStr", sqlStr);
    connection.query(sqlStr, function (error, results, fields) {
      if (error) {
        // throw error;
        console.log("数据库出错了", error);
      }
      console.log("执行成功", results);
      // 3、响应
      if (results.length == 1) {
        success();
      } else {
        fail();
      }
    });
    // 3)、关闭数据库
    connection.end();
  } catch (error) {
    res.json({
      code: "-1",
      msg: "token无效",
    });
  }
};
​
​
// 获取所有的商品数据
router.get("/", function (req, res, next) {
  // 1、接收前端的数据
  let goodsname = req.query.goodsname;
  let goodsid = req.query.goodsid;
​
  //2、验证token,如果成功获取数据。
  tokenVerify(
    req,
    res,
    function () {
      // 2、后端逻辑
      let sqlstr = "select * from goods where 1=1 ";
      if (goodsid != undefined) {
        sqlstr += ` and goodsid='${goodsid}'`;
      }
​
      if (goodsname != undefined) {
        sqlstr += ` and goodsname='${goodsname}'`;
      }
​
      console.log("sqlstr", sqlstr);
​
      // res.setHeader( "access-control-allow-origin","*");
​
      connection.query(sqlstr, function (error, results, fields) {
        if (error) {
          // 3、响应
          res.json({
            code: "0",
            msg: "数据库服务器出问题",
          });
        } else {
          console.log("获取到了商品列表数据");
          // 3、响应
          res.json({
            code: "200",
            data: results,
          });
        }
      });
    },
    function () {
      res.json({
        code: "-1",
        msg: "token不对",
      });
    }
  );
});
​
module.exports = router;
 

三、JWT(JSON WEB TOKEN)的两个函数

jsonwebtoken的安装引入

let jwt = require('jsonwebtoken')

生成签名(token)

let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])

[payload]  使用用户输入的信息(如:用户名),加密的原始字符串

[secretOrPrivateKey]  加密规则,字符串,或者私钥path模块,其实就是一串字符串(越乱越好)

[options]  可选配置项 ,如:expiresIn表示 过期时间(单位是秒)

[callback]  成功回调, 可选 返回制作后的token,也可同步返回;如果写了该回调函数就用的回调函数的异步操作,如果不写,那么同步返回

校验token

jwt.verify(token, secretOrPublicKey, [options, callback])

[token]  制作后的token

[secretOrPublicKey]  解密规则,字符串,或者公钥

[callback:]  回调 err 错误信息 decode 成功后的信息

[options]  expiresIn 过期时间

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值