Token的使用

网址:https://www.jianshu.com/p/58abb716b5dc/

具体概念参考上面链接

Token验证的基本流程

1.服务端收到请求,去验证用户名与密码
2.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
3.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
4.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
5.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

JWT标准的Token有如下三个部分

header (头部)
payload (数据)
signature (签名)

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJhZG1pbiIsInVzZXJfaWQiOjEsImlhdCI6MTU5NDI2MjQ5NSwiZXhwIjoxNTk0MzQ4ODk1fQ.1MJ_MAFgpBjOjpggj69Xz8F_evBcMAenRK_7a8fdVrc

安装

//生成token与验证
 1.jsonwebtoken
 npm install jsonwebtoken --save
 * 生成token的方法 sign
 * 验证token的方法 verify

2.express-jwt
 npm install express-jwt --save
* 验证token是否过期并规定那些路由不需要验证 express-jwt({})

token Express后端相关代码

定义生成token和获取token的函数

/token/token.js

const jwt = require('jsonwebtoken');

// 密钥
const jwtSecret = 'dkfjdjfkdfdfd';  //签名

//登录接口 生成token的方法
// setToken携带的参数及参数的数量自定义
const setToken = function (user_name) {
    return new Promise((resolve, reject) => {
        //expiresln 设置token过期的时间
        //{ user_name: user_name, user_id: user_id } 传入需要解析的值( 一般为用户名,用户id 等)
        // const token = jwt.sign({ user_name: user_name }, jwtSecret, { expiresIn: '24h' });
        const token = jwt.sign({ user_name: user_name }, jwtSecret, { expiresIn: '10s' });
        resolve(token)
    })
}
//各个接口需要验证token的方法
const getToken = function (token) {
    return new Promise((resolve, reject) => {
        if (!token) {
            console.log('token是空的')
            reject({
                error: 'token 是空的'
            })
        }
        else {
            // 验证token
            var info = jwt.verify(token.split(' ')[1], jwtSecret);
            resolve(info);  //解析返回的值(sign 传入的值)
        }
    })
}

module.exports = {
    setToken,
    getToken
}

解析token,验证token

app.js


const express = require("express")
const app = express()
//express跨域
const cors = require("cors")
// 生成token和验证token是否正确的函数
const vertoken=require('./token/token')

//验证token是否过期,并规定哪些路由不用验证token
const expressJwt=require('express-jwt')

const bookRouter = require("./router/bookRouter")
const userRouter = require("./router/userRouter")
app.use(cors())

//允许访问upload下的静态资源
app.use(express.static("upload"))
// 解析post请求的参数
app.use(express.json())

//=============================================验证token

//解析token获取用户信息
app.use(function(req, res, next) {
    let token = req.headers['authorization'];
    if(token == undefined){
        next();
    }else{
        vertoken.getToken(token).then((data)=> {
            console.log('解析后的token',data);
            req.data = data;
            next();
        }).catch((error)=>{
            next();
        })
    }
});

//验证token是否过期并规定那些路由不需要验证
app.use(expressJwt({
    secret:'dkfjdjfkdfdfd',
    // 加密算法
    algorithms:['HS256']
}).unless({
    path:['/login']  //不需要验证的接口名称
}))

//设置托管静态目录; 项目根目录+ public.可直接访问public文件下的文件eg:http://localhost:3000/images/url.jpg

//token失效返回信息
app.use(function(err,req,res,next){
    if(err.status==401){
        res.status(401).send('token失效11111111')
    }
})

app.use(bookRouter)
app.use(userRouter)

app.listen(3000, () => {
    console.log("服务器已开启在3000端口");
})


登录接口

/router/usersRouter.js

const express = require("express")
const router = express.Router()
const conn = require("../db/db")
const vertoken = require("../token/token")

// 查询商品
router.post("/login", (req, res) => {
    let { user_name, pw } = req.body;
    let sql = "select * from admin where user_name = ? and pw = ?"
    conn.query(sql, [user_name, pw], function (err, result) {
        if (err) {
            console.log('查询数据库失败');
        } else {
            let data;
            if (result.length) {
                //==============================================调用生成token的方法
                vertoken.setToken(user_name).then(token => {
                    data = {
                        code: 0,
                        message: '登录成功',
                        token: token
                        //前端获取token后存储在localStroage中,
                        //**调用接口时 设置axios(ajax)请求头Authorization的格式为`Bearer ` +token
                    }
                    res.send(data)
                })
            } else {
                data = {
                    code: 1,
                    msg: '登录失败 '
                }
                res.send(data)
            }
            
        }
    })
})


module.exports = router

token Vue前端相关代码

登录后获取token

login(this.ruleForm)
    .then((res) => {
        console.log('login返回的数据');
        if (res.data.code == 0) {
        this.$message({
            message: "登录成功",
            center: true,
        });

        //存储token
        localStorage.setItem("token",res.data.token)
        this.$router.push("/Layout")
        }
    });

前端请求携带token

api/config.js

import axios from 'axios'

// 给所有axios请求设置基础的域名
// axios.defaults.baseURL = 'http://localhost:3000'


//用axios.create可以创建axios的实例,允许不同实例有不同配置
const axios1 = axios.create({
    baseURL: 'http://localhost:3000',
    // 请求超时的时间
    timeout: 5000
}); 
// const axios2 = axios.create({
//     baseURL: 'http://www.test.com',
//     timeout: 5000
// });


//添加请求拦截器,会在发起请求之前执行相应的需求
axios1.interceptors.request.use(function (config) {
    // console.log('我是请求拦截器');
    config.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem("token");
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// //添加响应拦截器,会在返回数据后先执行相应的需求
axios1.interceptors.response.use(function (response) {
    console.log('我是响应拦截器');
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    console.log('error',error.status);

    return Promise.reject(error);
  });
export default axios1
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容

  • 项目中是使用Koa的搭建服务器。端口配置放在.env文件中,上传时应该忽略该文件,因为每个设备有自己的端口号。这里...
    哆啦_阅读 699评论 0 0
  • 一.为什么要使用token1.token完全有应用管理,它可以避开同源策略2.token可以避免CSRF攻击3.t...
    随风_283b阅读 3,520评论 0 1
  • 前后端分离以及token的使用 为什么使用前后端分离: 首先说一下jsp的工作原理: jsp实际上也是是一个继承自...
    韩who阅读 4,523评论 0 2
  • Android token使用 对于初学者来说,对Token和Session的使用难免会限于困境,开发过程中知道有...
    奈何心善阅读 3,133评论 2 3
  • JWT简介 JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑和自包含的方...
    BraveHeartLi阅读 13,286评论 1 29