【问题记录】小程序前后端联调
不明所以的问题记录~
目录
1、从数据库中获取中文是乱码的问题
其实一开始这个问题不是从命令行发现的,而是在小程序前端接口测试的时候,发送请求到后端发现拿回来的数据中的中文全是问号...
原因
- MySQL客户端输出窗口显示中文时使用的字符编码不对造成的,现在是使用utf8字符编码来显示中文数据的,但是因为操作系统是中文操作系统,默认使用的字符集是GB2312,所以需要把输出窗口使用的字符编码改成gb2312才能够正常显示中文;
- 欸是不是这个原因我也不知道,但是的确按照下面的方法改完就好了
解决方案
- 输入指令
show variables like ‘char%’;
查看数据库编码规则; - 其中的
character_set_results
是返回给用户的格式,要将其修改为gb2312就可以了:- 输入指令
set character_set_results=gb2312;
- 修改完毕再用上面的指令查看。
- 输入指令
- 结束之后,再在前端小程序和命令行中都看看从数据库获取到的中文是否还是乱码(反正我解决了)
2、KOA静态资源
前端页面在自己调试的时候图片还是正常加载出来了,但是一和后端联调就无法显示。
原因
- 前端调试的时候,静态图片都是直接放在前端文件夹里的,页面中直接使用相对地址获取到了图片,但是在联调的时候,浏览器会自动的把相对地址补全成绝对地址
- 补全的地址是错误的,所以我们需要自己把前端需要的图片地址转化为带有http请求的地址,去后端进行请求
解决方案
- 利用koa的第三方插件koa-static来帮助处理静态资源
- 使用方法如下
安装
npm i koa-static
使用
// 入口文件 app.js 中
// 用来处理路径的库 挺好的
const path = require('path')
// 导入koa-static
const static = require('koa-static')
// 注册中间件(足以见得static构造函数返回的也是一个函数)
app.use(static(path.join(__dirname, './static')))
// 要返回静态资源路径的 art.js 文件中
// 直接使用 当前url根路径+静态资源的相对路径即可
res.setDataValue('image', global.config.host + imgUrl)
- 其实构造的数据是这样的:http://localhost:3000/images/movie.8.png,但在koa-static插件的影响下,会将这里直接在根路径下请求的静态资源路径 经过刚刚在app.js中注册的中间件函数,转发到对应实际的静态资源路径下。
又出现新的问题
刚刚在art.js中将返回数据中的image路径改完,期刊部分的图片可以正常显示了,但是还有喜欢页面等其他所有页面中需要用到服务器静态资源的路径无法正常显示。难道要一个个加上吗?而且还涉及到循环遍历。。。
像这样要修改返回数据的问题,肯定是在越源头的地方修改越方便;
- 源头的话首先肯定想到的是直接在操纵数据库的工具文件中给image值加上一个get操作,sequelize的get是在读数据的时候修改值,我们就是需要在读数据的时候改变image的值,看起来很完美了。但是呢,不要忘记我们在Model模型原型链上加了toJSON方法,在返回数据的时候是从对象的dataValues中读的数据并返回,而get操作并不会修改值本身(dataValues里的数据),因此这样以来又功亏一篑了;
解决方案
- 在toJSON方法中,判断遍历dataValues中的数据 若遇到了不是以http开头(也就是还不是完整路径的image路径)的路径,就将其加成合理路径。
关于项目中静态资源的讨论
- 静态资源并不是只有图片,像html/js/css等文件也属于静态资源,一般静态资源都会放到如下几个地方:
- 网站目录,也就是直接在放在服务器代码的地方;
- 静态资源服务器,自己在本地/其他地方 搭建一个专门存放资源的服务器,注意要带宽足够,能够供很多人同时查询;
- 云服务,如OSS等;
- GitHub上的gitpage。
3、无感知刷新
当用户在登录的时候 令牌 还是有效在,随后用户进行一系列的请求数据的操作 在这过程中没有退出过,突然token无效了,这时候要如何保证用户在无感知情况下 重新获取令牌呢。
原因
- 用户在请求过程中token无效了,如果这时候不加什么操作 将会需要用户退出后再进来,体验太不好了吧。
解决方案
- 一开始还是在登录的时候进行token的判断,先从缓存中把token取出来检验是否合法,不合法就重新获取,合法就继续进行后续操作;
- 用户在发送请求的过程中,token突然失效,这时候需要再次向服务器请求新的token,保存在缓存,并且重新发送用户需要数据的请求,二次重发机制,也就是我们来帮用户重新发送这次请求,而不是用户自己再去点。
- 流程大概就如下图所示,看起来好像很简单哦 只要当返回403(forbidden 说明token不合法)时候重新申请token再发送新请求就好了,但是这里面过程还是没那么简单!如何让代码精简也是一大难点呢。
// 在http-p.js中 请求success函数里加上一条这样的语句
else if (statusCode.startsWith('403')) {
if (reFetch) { // 这个变量是为了保证不会多次重发
this._reFetch(url, resolve, reject, method, data)
}
}
// 在下面加上这个函数
_reFetch (...params) {
// 重新获取token
tk.getToken().then(res => {
// 重发请求
// 这里传的reFetch是false代表 这就是二次重发的第二次了 后续不要再发了
this._request(...params, false)
})
}
4、双令牌机制
第三点提到的无感知刷新是在不需要用户输入账号密码的情况下使用的,因为token是直接保存在缓存里,用的时候也是直接从缓存里取出来,但是账号密码呢?也是直接保存在缓存里吗?那是不是有点憨了... 所以就引出了双令牌机制。
哪两个令牌
- access_token:普通的令牌,和上面说的一样,过期时间一般比较短,几个小时左右;
- refresh_token:用来刷新的令牌,如果access_token过期了就通过refresh_token来更新access_token,过期时间一般比较长,一个月左右。
实现目的及原理
- 主要还是要实现在用户无感知的刷新,但如果refresh_token也只是在固定时间内过期,那么不管这一个月内用户使用该小程序频率是怎样 都会在一个月之后过期,又要重新输入密码...明明一直在使用但是突然有一天要你重新输入账号信息,是不是很懵;
- 所以refresh_token不能简单的在固定时间内过期,而是要在access_token过期更新的时候,也进行一次刷新
- 比如 access_token 两小时之后过期了,利用refresh_token更新一次,这个时候refresh_token本身也进行一次更新,还是在一个月之后过期,但这次一个月是新的一个月,也就是相对于这两小时过了之后的一个月;
- 这样一来就可以实现,只有用户在一个月内一直从未访问过小程序才会需要重新输入信息,如果一直在使用,是不需要重新验证的,和当前大多数业务也比较相符。