前后端交互

jwt (JSON web token)

简介

判断你是否有权限和服务器进行交互,相当于一个门禁吧,过程如下

在这里插入图片描述

知识点补充

token:服务端登录成功后进行签发
哈希:对复杂的数据进行摘要,10G 的内容,如果改了1kb ,那么它的哈希值也会改变的

实现方式

流程:我们以登录过程为例子,登录成功后签发 token,访问接口时携带 token

签发 Token

可以通过 jsonwebtoken 这个模块去签发 token参考 npm 上的模块说明,也可以参考 https://jwt.io/ 查看 token 的信息
在这里插入图片描述

签发的过程如下

const jwt = require('jsonwebtoken') // 签发 token 的模块
let token = jwt.sign(
    {
        name: 'some value',
    },							// token 中携带的一些参数,你可以自己写,用 base64 加密的
    'mytoken',					// 秘钥名称,等会用来鉴权时会用到
    { expiresIn: '2h' }         // 时效性,一般都是 2   个小时
)

后端签发好 token 后,发送给前端,前端需要保存好token,可以放到cookie 或者 localStorage 里(推荐放到localStorage

鉴权

当前端去访问后台接口时,需要在请求头中带上你的 token,注意要声明一下 Bearer

// 前端
function checkApi() {
    let xhr = new XMLHttpRequest()
    // 需要把 token 放到头部带回服务端;
    xhr.open('get', '/checkApi', true)
    if (localStorage.getItem('token')) {
        xhr.setRequestHeader(
            'Authorization',
            'Bearer ' + localStorage.getItem('token')
            // 如果后端是通过 jwt,这边就需要声明一下 Bearer!!!!
        )
    }
    xhr.onload = function () {
        // console.log(JSON.parse(xhr.responseText));
        let res = JSON.parse(xhr.responseText)
        console.log(res)
        //  存token;
    }
    xhr.send()
}

携带好头信息后,后端接口可以这样校验,首先要引入 koajwt 这个模块,然后再写接口时,第二个参数写秘钥的名称koajwt({ secret: 'secretKey' }),举例子的话就是以下这样

const koajwt = require('koa-jwt')   // 鉴权

// 这边会自动鉴权
router.get('/checkApi', koajwt({ secret: 'mytoken' }), (ctx) => {
    ctx.body = {
        test: 'value..',
    }
})```

图片展示如下:
在这里插入图片描述
同源情况下,如果没有权限的话,会报 401 的权限错误,返回 Authentication Error 的报错信息
在这里插入图片描述非同源去检验权限的话报如下的错误,这里不是很明白,为什么 token 错了会报这个错误呢?

在这里插入图片描述

成功的话就是正常的接口返回了
在这里插入图片描述
至此简单的 jwt 就结束了


请求工具

这里介绍几种方法,axios 以及 fetchaxios 比较常用

Axios

基础用法

axios 有两种常用的使用方法

第一种

axios({
    method: 'post',
    url: 'http://localhost:4000/checkUser',
    data: {
        username: '张三',
        password: '123',
    },
    headers: {},
}).then((res) => {
    console.log(res)
    if (res.data.token) {
        localStorage.setItem('token', res.data.token)
    }
})

第二种

axios
    .post('http://localhost:4000/checkApi', data, {
        headers: {
            Authorization:
                'Bearer ' + localStorage.getItem('token'),
        },
    })
    .then((res) => console.log(res))

在这里插入图片描述

网络拦截

回到刚才的问题上!

提出问题

如果有很多接口都需要验证 token ,那么我们不能在每个接口里都要写验证的语句,那样的话代码就会冗余
有什么办法统一处理这些呢?

就是用拦截器。

Axios 中的拦截器

在每一个 axios 请求的时候都会走拦截器

axios.interceptors.request.use((config) => {
    return config
})
axios.interceptors.response.use((res) => {
    return res
})

拦截器可以有多个,比方说下面的例子,我们在关心一下拦截器的顺序:

/**
 * 拦截器,所有的 axios 请求都会走这里
 **/

//  请求拦截器
axios.interceptors.request.use((config) => {
    console.log('请求拦截器1:>>', config)
    if (localStorage.getItem('token')) {
        // 在拦截器里去配置 token
        config.headers.Authorization =
            'Bearer ' + localStorage.getItem('token')
    }
    return config
})
axios.interceptors.request.use((config) => {
    console.log('请求拦截器2:>>')
    return config
})
axios.interceptors.request.use((config) => {
    console.log('请求拦截器3:>>')
    return config
})
// 响应拦截器
axios.interceptors.response.use((res) => {
    // console.log(config)
    console.log('响应拦截器1:>>', res)
    return res
})
axios.interceptors.response.use((res) => {
    // console.log(config)
    console.log('响应拦截器2:>>', res)
    return res
})
axios.interceptors.response.use((res) => {
    // console.log(config)
    console.log('响应拦截器3:>>', res)
    return res
})

打印的顺序如下图所示:

在这里插入图片描述
根据顺序可以分析出,配置能够被冲掉

在这里插入图片描述

简版 Axios

抽离出来了:https://blog.csdn.net/u010263423/article/details/119274544


fetch

  • 原生的,基于 Promise 封装的
  • 默认是 get 请求。
  • react native 用的挺多。
简单案例
fetch('/fetchtest', {
    method: 'post',
    body: 'name=张三&age=10', // 发送的内容写在body里了,相当于 axios 中的 data
    headers: {
     	// 默认的应该是:Content-Type: text/plain;charset=UTF-8
        'content-type': 'application/x-www-form-urlencoded',
        // 前端设置了这个,后台就会在 request.body 里收到 json 格式的数据
    },
    // content-type 描述的东西要和 body 对应上!
})
    .then((res1) => {
        console.log('res1:>>', res1) // 并不是我们想要的结果,而是 response 对象
        // return res1.text()
        // return res1.clone()      // 对当前数据进行  深拷贝
        return res1.json() // 返还个 json,在第二个then 里能用到
    })
    .then((res2) => {
        console.log('res2:>>', res2)
    })
fetch('/fetchtest', {
    method: 'post',
    body: JSON.stringify({ name: '张三' }), //这里如果有 'name=张三&age=10'
    headers: {
        'content-type': 'application/json',    // content-type 描述的东西要和 body 对应上!
    },
})

也可以实例化一个 headers 对象,然后追加,最后赋值给 headers 即可。

let myHeader = new Headers()
myHeader.append('Content-type', 'application/json')
myHeader.append('myTest', '123')

在这里插入图片描述
在这里插入图片描述

缺点
  • 不能上传文件
  • 兼容性,不如 xmlHttpRequest

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐