入门级node+uni-app开发即时通讯聊天室(2)基于token的安全验证应用 (三)

前言: 仔细想想我们现在的服务器应用是否不太安全?只要你的请求路径被得知,你的接口就会被任何来源的用户所使用,这显然不是我们所希望的。接下来就到解决这个问题。

JWT 的原理
JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样。
{
“姓名”: “张三”,
“角色”: “管理员”,
“到期时间”: “2018年7月1日0点0分”
}
以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。
服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

上面摘自http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html。
其中的JWT全名JsonWebToken,是实现token技术的一种解决方案。

JWT 的使用方式
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

通过这种方法,我们就可以实现只有登录的用户(在token未泄露的情况下),才能调用我们服务器的接口,去请求数据。好了,接下来就是去实现将这个方案运用到我们的项目中。

npm install jsonwebtoken --save OR
cnpm install jsonwebtoken --save

在config配置目录下添加token.js文件,我们暂时只需在user模块登录的时候将这个模块引入。
在这里插入图片描述
jwt在服务器使用这个密钥注册一个token对象,expiresIn有过cookie使用的应该很容易想到,这就是过期时间的设置。载荷是存放有效信息的地方,它可以接受三种声明,标准中注册的声明,公共的声明,私有的声明。这里我们使用的是公共的声明,可以添加任何的信息。通过这个唯一的id我们可以生成唯一的token。

为了保证我们的用户可以使用token,我们应该在登录的地方再做一些处理,将token返回到前端,同时前端负责把他持久的存储进客户端。
在这里插入图片描述

引入token模块,在确认登录前生成一个token让他返回前端。同时你可能注意到我这加了个字段user_imgurl,别嫌麻烦,回去dao目录下再添加一个返回字段把。
先测试一下我们的token是否能正常返回了。
在这里插入图片描述
到这已经完成了一半了,还有一半就是客户端发送请求时携带上服务器端返回的token,同时服务器对请求进行token验证。
先进行服务器端的token验证,我们限定客户端发起请求的时候请求头要加上’Authorization’字段,他的值是token
在这里插入图片描述

如果当前被请求的地址是登录或者注册的接口我们直接放行,如果不是这两个地址,我们就要进行token验证。那么我们试试这段代码是否已经跑通了。
在这里插入图片描述
成功了,我们已经能做到不使用token请求的话就无法访问服务器的资源。客户端发送请求时需要带上token,那这个token首先得保存在客户端中,然后在请求的时候请求头中发送出去。
在这里插入图片描述
首先在前端将token存储进去,那这个时候问题就来了,我们肯定不希望每次写请求的时候都得在原生的方法的header中添加token字段,我们应该希望每一次请求都自动的携带上我们保存好的token。这个时候我们就得封装一下原生的请求方法了。

在前端的common\js下新建文件http.js

const sendRequest = (url,method = 'GET',data = {},contentType) => {
	url = 'http://localhost:3000'+ url;
	let token = uni.getStorageSync('token') || '';
	console.log(url);
	return new Promise(function(resolve,reject){
		uni.request({
			url,
			data,
			method,
			header: {
			    'Content-Type': 'application/json',
				'Accept': 'application/json, text/javascript, */*; q=0.01',
				'Authorization': token
			},
			success: function(res){
				if(res.header.authorization){
					uni.setStorageSync('token',res.header.authorization);
				}else{
					var code = res.statusCode;
					switch (code) {
						case 403:
							uni.showModal({
								title: '登录提示',
								content: '身份已过期,请重新登录后再来操作!',
								success:res => {
									if (res.confirm) {
										uni.clearStorageSync('token');
										uni.redirectTo({
											url:'/pages/login/login.vue'
										})
									}
								}
							})
							break;
						default:
							resolve(res);
							break;
					}
				}
			}
		})
	})
}

我们做下测试,先把服务端的signup 加以限制,不允许他直接越过token检测。在main.js里把他挂载到原型实例上。

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

测试下。发现结果并不如我们的预期
在这里插入图片描述
我尽可能的描述下这个现象产生的原因吧。他的意思是我们不能在客户端里访问一个服务器端未被返回的字段。好,那我们根据它的要求修改一下服务器的配置,在’Access-Control-Allow-Headers’: 'X-Requested-With,Content-Type‘ 里加上authorization

为什么这么做?其实我们完全可以把上面封装的http方法的 res.header.authorization)去掉,因为我们知道我们写的这个服务器端对于token的传送方式是直接通过登录的时候返回,而不是把他放在请求头中给客户端。你可以纯当我就额外的添加了一个多余的知识点吧。

再测试。这次到后端报错了,那这个错误我们就好理解了,jwt没有提供,那我们就给他提供呗。
在这里插入图片描述
在’Access-Control-Request-Headers’: ’ Origin, X-Requested-With, content-Type, Accept,Authorization’,添加Authorization认证字段(这里稍微解释下为什么上面的获取req.headers.authorization,是因为发送请求的时候,请求头的字符会被默认转换为小写),前端的http方法请求的时候已经带上了token,那这次我们再测试一下。
在这里插入图片描述
成功了!至此基于token的安全验证已经实现了,我们客户端请求的时候只要使用我们封装好的方法,使它自己带上token进行请求。最后别忘了在app.js中把我们的放行路径给添加上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值