鉴权:cookie, session和token

鉴权:cookie, session和token

一切都来源于http是一个无状态的协议,故而浏览器对于服务器的每一次相同的请求都是相同的。正是由于这个原因,服务器无法判断用户的状态,故而有了cookie, session, token, sessionStorage, localStorage的出现。

cookie的作用是存储用户数据以用于给服务器端判断用户状态,这些数据存储在用户电脑上。浏览器在每一次向服务器发出请求的时候cookie都会被顺带着发送给服务器,服务器会拿到cookie并从中获取一些用户信息。这些信息可能是用户的身份识别信息、会员识别信息等等。

cookie是一个字符串,它的形式是:
"cookie_name1=cookie_value1; cookie_name2=cookie_value2; ...; expires=Thu, 18 Dec 2099 12:00:00 GMT; path=/"

cookie又分为内存cookie(非持久化存储)和磁盘cookie(持久化存储)。


cookie和session

cookie和session的产生过程

浏览器首次请求服务器时,服务器会在本地建立一个session并返回给浏览器一个 Set-Cookie 响应头(包含了sessionid),浏览器拿到这个响应头就会去设置cookie。
随后浏览器再次请求这个服务器的时候,随着用户对于页面的操作,就会修改cookie的值,后面每次浏览器请求服务器cookie都会被发送给服务器。

cookie原理

session原理

故而,cookie就是用户的身份识别信息,session就是服务端用来识别客户端cookie的一条记录。

cookie是实现session方案之一,现在一般是cookie+session的方式记录。

创建cookie

创建cookie(默认)

1
document.cookie = "username=Mason";

默认情况下:cookie会在浏览器关闭时删除。

创建cookie(设置时效)

1
document.cookie = "username=Mason;expires=Thu, 18 Dec 2099 12:00:00 GMT";

指定cookie路径

默认情况下:cookie属于当前页面。

告诉浏览器cookie路径:

1
document.cookie = "username=Mason;expires=Thu, 18 Dec 2099 12:00:00 GMT;path=/";

读取cookie

1
2
var ck = document.cookie;
// ck是一个字符串,其内容是cookie_name1=cookie_value1;cookie_name2=cookie_value2;cookie_name3=cookie_value3;...

想进一步查找一个 name/value 就必须采用字符串方法查找。

还有一点就是cookie只能被其所在的domain的服务器所读取,也就是说cookie的domain值需要和服务器的domain一样才会被浏览器发送给服务器。

修改cookie

1
document.cookie = "username=Ryan;expires=Thu, 18 Dec 2099 12:00:00 GMT;path=/";

删除cookie

1
2
// 将cookie设置为历史日期既可,指定cookie的name既可
document.cookie = "new_cookie_name=;expires=Thu, 01 Jan 1970 00:00:00 GMT";

也可以先 new Date() 获取当前时间,然后在此基础上减去一定的时间,再将 expires 设置为这个时间既可。

如果使用修改cookie的方法给cookie赋空值则cookie的name依然存在。

使用devtools查看cookie

除了使用代码之外,还可以打开浏览器devtools -> application -> storage -> cookies查看到cookie。

cookie的寿命

cookie默认的寿命是直到浏览器被关闭。

后端可以使用一些方法来设置cookie的寿命。

java为例:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// new一个Cookie实例
Cookie cookie = new Cookie("username", "Mason");

// 设定cookie寿命为1年
cookie.setMaxAge(60*60*24*365);

// 设定cookie寿命为关闭浏览器之前
cookie.setMaxAge(-1);

// 设定cookie为已过期
cookie.setMaxAge(0);

// 将cookie写入浏览器
response.addCookie(cookie);

实例:设置、获取、检测cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}

function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}

function checkCookie() {
var user = getCookie("username");
if (user != "") {
alert("欢迎 " + user + " 再次访问");
} else {
user = prompt("请输入你的名字:", "");
if (user != "" && user != null) {
setCookie("username", user, 30);
}
}
}

相同点

他们都是用于存储用户数据的方式。

不同点

  1. cookie每次都会被浏览器发送给服务器,sessionStorage和localStorage不会被浏览器主动发送给服务器。
  2. cookie有寿命,sessionStorage只对当前页面有效且仅存在于页面关闭之前,localStorage可以被多个页面共享且会一直存在于用户电脑上。

cookie作用:验证用户登录

如果在一个网站比如腾讯视频已经登陆过了账号,那么下次打开该网站的时候服务器是怎么知道我们已经登陆了会员的呢?

服务器会在用户登陆了网站的时候返回一个 Set-Cookie 响应头,这个响应头标识了用户的登录凭证。浏览器将它存储在本地,在下一次浏览器再一次打开这个网站的时候这个凭证就会被一同发送给服务器。服务器通过读取之前存储在数据库中的用户凭证来和浏览器发送过来的作比对,相同则服务器会根据该用户的信息渲染对应的前端页面并返回给用户的浏览器。

token

token(令牌)是一种服务器端无状态(服务器端不存放用户身份信息)的认证方式。

组成

格式:uid(用户身份标识) + time(时间戳) + sign(签名) + 固定参数

token认证过程

  1. 用户登录后服务器返回一个token给客户端。
  2. 客户端将token保存在本地。
  3. 客户端再次访问服务器的时候token会被携带在headers中。
  4. 服务器校验token。

基于token的交互

token的组成:

  • Header 头部信息:记录了使用的加密算法信息;
  • Payload 净荷信息:记录了用户信息和过期时间等;
  • Signature 签名信息:根据 header 中的加密算法和 payload 中的用户信息以及密钥key来生成,是服务端验证服务端的重要依据。

token的组成

相比于cookie和session的优势

  • Token 可以跨站共享,实现单点登录;
  • Token 机制无需太多存储空间。Token 包含了用户的信息,只需在客户端存储状态信息即可,对于服务端的扩展性很好;
  • Token 机制的安全性依赖于服务端加密算法和密钥的安全性;
  • Token 机制也不是万金油。

JWT(json web token)

客户端获取了服务端的token之后将它保存在本地localStorage中。以后客户端每次访问服务端都传token到服务端,服务端通过解密token识别用户身份从而提供服务。而服务端本地不存储用户状态信息从而服务器时无状态的,这样服务端就可以做基于无状态的负载均衡,这就是JWT。

评论