访问者身份验证-token---kalrry
一、实现原理/业务场景
1. 身份验证
HTTP 是一种没有状态的协议,也就是它并不知道是谁访问(或者说,没法区分,每次的访问和以前哪次的访问来自同一个客户端)。客户端用户名密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证 session(会话)
2. 实现原理
-
当用户打开浏览器,首次访问某个网站(服务器),服务器会产生一个唯一的编号(sessionId),在响应时,把该编号发给客户端,客户端把该编号存储在cookie里。
-
当用户二次访问(如:点击超链)服务器,那么,请求时,会携带保存在cookie里的编号,服务器端拿到该编号后,会跟session中的编号进行对比,就能知道本次访问和哪次访问是同一个客户端。
3. 业务场景
- 客户端发送用户名和密码,请求登录
- 服务端收到请求,去库验证用户名与密码
- 验证成功后,服务端种一个cookie或发一个字符到客户端,同时服务器保留一份session
- 客户端收到 响应 以后可以把收到的字符存到cookie
- 客户端每次向服务端请求资源的cookie会自动携带
- 服务端收到请求,然后去验证cookie和session,如果验证成功,就向客户端返回请求的库数据
Session存储位置: 服务器内存,磁盘,或者数据库里
Session存储内容: id,存储时间,用户名等
客户端携带 : cookie自动带
二、express-session
- 引入session模块: var session = require(‘express-session’);
- 创建session中间件
app.use(session(options));
示例:
app.use(session({
secret: 'recommend 128 bytes random string',
cookie: { maxAge: 20 * 60 * 1000 },//session的过期时间(没有错,cookie和session息息相关,所以,是用cookie.maxAge来设置session的过期时间)
resave: true,
saveUninitialized: true
})
);
- 保存变量:
req.session.变量名= 值;
- 获取变量:
req.session.变量名
扩展:session 登录和其它需要验证身份的模块(如:添加,删除)
三、token
目前token比较流行
1. 实现原理
在服务端不需要存储用户的登录记录,全部发给客户端由客户端自己存(cookie,localStorage)
1、客户端使用用户名跟密码请求登录(前端)
2、服务端收到请求,去验证用户名与密码 (后端)
3、验证成功后,服务端会签发(产生)一个 Token(加了密的字符串),再把这个 Token 发送给客户端(后端)
4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里(前端)
5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token(前端)
6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
示例:vue项目(webserver)和nodejs项目(apiserver)使用token。
2. 实现
- jsonwebtoken的安装引入
let jwt = require('jsonwebtoken')
- 生成签名(token)
let token = jwt.sign(payload, secretOrPrivateKey, [options, callback])
- 校验token
jwt.verify(token, secretOrPublicKey, [options, callback])
- token删除
由客户端,负责删除,服务器端没有任何保存,所以,只需要在客户端删除就行。
示例:token 登录,其它需要验证身份的模块(如:添加,删除)
四、session 与 token 区别
功能 | session | token |
---|---|---|
服务端保存用户信息 | √ | × |
避免CSRF攻击 | × | √ |
多服务器粘性问题 | 存在 | 不存在 |
多服务器粘性问题 |
当在应用中进行 session的读,写或者删除操作时,会有一个文件操作发生在操作系统的temp 文件夹下,至少在第一次时。假设有多台服务器并且 session 在第一台服务上创建。当你再次发送请求并且这个请求落在另一台服务器上,session 信息并不存在并且会获得一个“未认证”的响应。这时候,就需要把在第一台服务器上保存的session给其它服务器上也保存。然而,在基于 token 的认证中,这个问题很自然就被解决了。没有粘性 session 的问题,因为在每个发送到服务器的请求中这个请求的 token 都会被拦截
对于注销登录来说,token只需要在客户端删除就行
五、保存信息给浏览器(cookie)
1.前端保存:
cookie/localstorage
2.后端操作cookie:
服务器给浏览器种cookie: cookie-parser
Cookie的创建(express会将其填入Response Header中的Set-Cookie)
格式:
- 添加cookie
res.cookie(name, value [, options]);
//参数:
name: cookie名
value: 类型为String和Object。
Option: 类型为对象,可使用的属性如下:
domain:cookie在什么域名下有效,类型为String,。默认为网站域名
expires: cookie过期时间,类型为Date。如果没有设置或者设置为0,那么该cookie只在这个session有效
maxAge: 实现expires的功能,设置cookie过期的时间,类型为String,指明从现在开始,多少毫秒以后,cookie到期。
path: cookie在什么路径下有效,默认为'/',类型为String
secure:只能被HTTPS使用,类型Boolean,默认为false
- 删除cookie
res.clearCookie(name [, options]);
- 获取cookie
req.cookies.键名 //cookie是在客户端保存,每次请求时会携带,所以,用req对象获取cookie
示例:
设置键为name,值为:baobao,可访问的域名为:.example.com,可访问的路径:/admin',只可以用https访问
res.cookie('name', 'baobao', {
domain: '.example.com',
maxAge:10000*1000,
path: '/admin',
secure: true
});
cookie的value为对象
res.cookie('cart', { items: [1,2,3] });
服务器给浏览器种cookie的同时在服务器上生成session: cookie-session
https://blog.csdn.net/qq_43051529/article/details/82871417