J'Blog

token登录验证&谷歌二次验证

token登录验证&谷歌二次验证

http是无状态的,那么应该如何记住登录状态呢?

以前的做法是在客户端cookie中保存sessionId,服务器端的session中保存sessionId,每次客户端发送请求的时候都带上sessionId,在服务端进行验证。

现在前后端分离,由于服务器之间不能共享内存,因此服务器之间session不能互通,因此不能使用session去存储用户的登录信息,一般使用token方式去记录登陆状态。区别就是token使用Redis缓存去存储这个用户标识。

token进行登录验证的步骤如下

1. 客户端输入用户名和密码向服务端发起验证

2. 服务端验证通过之后根据某种规则声称用户的token并返回,这个token保存在redis中,保证不同服务器间共享

3. 客户端存储该token,可以存储在sessionStorage或者cookie中

4. 后续服务器的每次请求都在请求头携带token发送到服务端

5. 服务端在执行方法前先对请求进行验证,取出token查询redis中有没有对应的值

前端使用的技术

以vue.js前端框架为例,用到的关键技术有路由导航守卫和拦截器

路由导航守卫主要是保证没有获得token时不能访问除登录外的其他页面,这里不对token进行验证,只是判断token存不存在,拦截器主要目的是让请求头携带token

	//路由导航守卫控制访问权限
	//为路由对象,添加beforeEach 导航守卫
	router.beforeEach((to, from, next) => {
		if(to.path === '/login') return next()
		const tokenStr = window.sessionStorage.getItem('token')
		if(!tokenStr) return next('/login')
		next()
	})

	//退出功能
	//基于token的方式实现退出只需要销毁本地的token即可
	window.sessionStorage.clear()
	this.$router.push('/login')

	//通过axios请求拦截器添加token,保证拥有获取数据的权限
	axios.interceptors.request.use(config => {
		config.headers.Authorization = window.sessisonStorage.getItem('token');
		return config;
	})

JWT(JSON WEB TOKEN)

jwt的构成分为三部分:

第一部分头部(header):两部分信息:

- 声明类型

- 声明加密的算法 通常直接使用HMAC SHA256

完整的头部就像下面这样的JSON

{
	'typ': 'JWT',
	'alg': 'HS256'	
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分

第二部分(payload),存放有效信息,包含三个部分:

- 标准中注册的声明

- 公共的声明

- 私有的声明

第三部分(signature),签证信息,由三个部分组成:

- header(base64后的)

- payload(base64后的)

- secret

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

如何应用jwt

一般是在请求头里加入Authorization,并加上Bearer标注:

fetch('api/user/1', {
	headers: {
		'Authorization': 'Bearer' + token
	}
}

有点:

- 因为json的通用性,所以jwt是可以进行跨语言支持的,像java,javascript,nodejs,php等很多语言都可以使用

- 因为有了payload部分,所以jwt可以再自身存储一些其他业务啥逻辑所需要的非敏感信息

- 不需要在服务端保存会话信息,所以它易于应用的扩展

项目中使用到的二次验证

两步验证已经被广泛应用于各种互联网应用当中,用来提供安全性。

对于如何使用两步验证,大家并不陌生,无非是开启两步验证,然后出现一个二维码,使用支持两步验证的移动应用比如 Google Authenticator 或者 LassPass Authenticator 扫一下二维码。

这时候应用会出现一个 6 位数的一次性密码,首次需要输入验证从而完成开启过程。

以后在登陆的时候,除了输入用户名和密码外,还需要把当前的移动应用上显示的 6 位数编码输入才能完成登陆。

这个过程的背后主要由两个算法来支撑:HOTP 和 TOTP。