cookie、session和token

https://zhuanlan.zhihu.com/p/25495290?utm_source=wechat_session&utm_medium=social

一、cookie

  众所周知,HTTP 是一个无状态协议,所以客户端每次发出请求时,下一次请求无法得知上一次请求所包含的状态数据,如何能把一个用户的状态数据关联起来呢?

  1、首先产生了 cookie 这门技术来解决这个问题,cookie 是 http 协议的一部分,它的处理分为如下几步:

1 服务器向客户端发送 cookie。
2 通常使用 HTTP 协议规定的 set-cookie 头操作。
3 规范规定 cookie 的格式为 name = value 格式,且必须包含这部分。
4 浏览器将 cookie 保存。
5 每次请求浏览器都会将 cookie 发向服务器。

  2、其他可选的 cookie 参数会影响将 cookie 发送给服务器端的过程,主要有以下几种:

1 path:表示 cookie 影响到的路径,匹配该路径才发送这个 cookie。
2 expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。一般用来保存 session 的 session_id。
3 secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
4 httpOnly:浏览器不允许脚本操作 document.cookie 去更改 cookie。一般情况下都应该设置这个为 true,这样可以避免被 xss 攻击拿到 cookie。

  3、express 中的 cookie

  express 在 4.x 版本之后,session管理和cookies等许多模块都不再直接包含在express中,而是需要单独添加相应模块。

var express = require(‘express‘);
// 首先引入 cookie-parser 这个模块
var cookieParser = require(‘cookie-parser‘);
var app = express();
app.listen(3000);
// 使用 cookieParser 中间件,cookieParser(secret, options)
app.use(cookieParser());
app.get(‘/‘, function (req, res) {
// 如果请求中的 cookie 存在 isVisit, 则输出 cookie
// 否则,设置 cookie 字段 isVisit, 并设置过期时间为1分钟
if (req.cookies.jack) {
console.log(req.cookies.jack);
res.send("welcome");
} else {
res.cookie(‘jack‘, ‘content‘, {maxAge: 60 * 1000});
res.send("no cookie");
}
});

  

  这里开发调试的时候用supervisor来启动,代码有改动,它会自动重启,避免不必要的手动重启工作。

  

  新版本的开发者工具界面,在application里面可以看到cookies 这些存储

  

  现在我们看到一个cookie名字为jack 内容为content的cookie就存储了,时间期限也有。

  如果没有设置时间(maxage/expires),

  那就是session cookie,

  浏览器关闭的时候cookie就没了。

二、session

  cookie 虽然很方便,但是使用 cookie 有一个很大的弊端,cookie 中的所有数据在客户端就可以被修改,数据非常容易被伪造,那么一些重要的数据就不能存放在 cookie 中了,而且如果 cookie 中数据字段太多会影响传输效率。为了解决这些问题,就产生了 session,session 中的数据是保留在服务器端的。

  session 的运作通过一个session_id来进行。session_id通常是存放在客户端的 cookie 中,比如在 express 中,默认是connect.sid这个字段,当请求到来时,服务端检查 cookie 中保存的 session_id 并通过这个 session_id 与服务器端的 session data 关联起来,进行数据的保存和修改。

  这意思就是说,当你浏览一个网页时,服务端随机产生一个 1024 比特长的字符串,然后存在你 cookie 中的connect.sid字段中。当你下次访问时,cookie 会带有这个字符串,然后浏览器就知道你是上次访问过的某某某,然后从服务器的存储中取出上次记录在你身上的数据。由于字符串是随机产生的,而且位数足够多,所以也不担心有人能够伪造。伪造成功的概率比坐在家里编程时被邻居家的狗突然闯入并咬死的几率还低。

  1、session 可以存放在地方

  1)内存

  2)cookie本身

  3)redis 或 memcached 等缓存中

  4)数据库中。

  线上来说,缓存的方案比较常见,存数据库的话,查询效率相比前三者都太低,不推荐;cookie session 有安全性问题,下面会提到。

  2、express 中操作 session

  express 中操作 session 要用到express-session(expressjs/session: Simple session middleware for Express) 这个模块,主要的方法就是session(options),其中 options 中包含可选参数,主要有:

1 name: 设置 cookie 中,保存 session 的字段名称,默认为connect.sid。
2 store: session 的存储方式,默认存放在内存中,也可以使用 redis,mongodb 等。express 生态中都有相应模块的支持。
3 secret: 通过设置的 secret 字符串,来计算 hash 值并放在 cookie 中,使产生的 signedCookie 防篡改。
4 cookie: 设置存放 session id 的 cookie 的相关选项,默认为(default: { path: ‘/‘, httpOnly: true, secure: false, maxAge: null })
5 genid: 产生一个新的 session_id 时,所使用的函数, 默认使用uid2这个 npm 包。
6 rolling: 每个请求都重新设置一个 cookie,默认为 false。
7 resave: 即使 session 没有被修改,也保存 session 值,默认为 true。

  3、在内存中存储 session

  express-session默认使用内存来存 session,对于开发调试来说很方便

var express = require(‘express‘);
// 首先引入 express-session 这个模块
var session = require(‘express-session‘);
var app = express();
app.listen(5000);
app.use(cookieParser(‘jack2016‘));
//解析cookie secret为‘jack2016’的cookie,可不可以不写secret?不写会报错
}));
// 按照上面的解释,设置 session 的可选参数
app.use(session({
secret:‘jack2016‘,
// 建议使用 128 个字符的随机字符串,这里不写secret的话cookie存储的是不加密的sessionid
name:‘jacks‘, //cookie名字,这里cookie存的内容是用secret加密的sessionid,
cookie: {maxAge:60*2000},//cookie设置,maxAge设置时间好像受到限制,太小直接没效,设置的够大无论是60*60还是60*60*24*12好像都是固定的4小时,这里有点疑惑。
}));
/* GET home page. */
router.get(‘/‘,function(req,res,next) {
console.log(req.sessionID,req.cookies.jack,req.signedCookies.jack);
res.render(‘index‘,{title:‘Express‘});
});

  signedCookie

cookie 虽然很方便,但是使用 cookie 有一个很大的弊端,cookie 中的所有数据在客户端就可以被修改,数据非常容易被伪造

  其实不是这样的,那只是为了方便理解才那么写。要知道,计算机领域有个名词叫签名,专业点说,叫信息摘要算法。

三、token

  API使得传统的前端和后端的概念解耦。开发者可以脱离前端,独立的开发后端,在测试上获得更大的便利。这种途径也使得一个移动应用和网页应用可以使用相同的后端。

  当使用一个API时,其中一个挑战就是认证(authentication)。在传统的web应用中,服务端成功的返回一个响应(response)依赖于两件事。一是,他通过一种存储机制保存了会话信息(Session)。每一个会话都有它独特的信息(id),常常是一个长的,随机化的字符串,它被用来让未来的请求(Request)检索信息。其次,包含在响应头(Header)里面的信息使客户端保存了一个Cookie。服务器自动的在每个子请求里面加上了会话ID,这使得服务器可以通过检索Session中的信息来辨别用户。这就是传统的web应用逃避HTTP面向无连接的方法(This is how traditional web applications get around the fact that HTTP is stateless)。

  API应该被设计成无状态的(Stateless)。这意味着没有登陆,注销的方法,也没有sessions,API的设计者同样也不能依赖Cookie,因为不能保证这些request是由浏览器所发出的。自然,我们需要一个新的机制。这篇文章关注于JSON Web Tokens,简写为JWTs,一个可能的解决这个问题的机制。这篇文章利用Node的Express框架作为后端,以及Backbone作为前端。

  1、背景

  我们来简短的看一下几个通常的保护(secure)API的方法。

  第一个是使用在HTTP规范中所制定的Basic Auth, 它需要在在响应中设定一个验证身份的Header。客户端必须在每个子响应是附加它们的凭证(credenbtial),包括它的密码。如果这些凭证通过了,那么用户的信息就会被传递到服务端应用。

  第二个方面有点类似,但是使用应用自己的验证机制。通常包括将发送的凭证与存储的凭证进行检查。和Basic Auth相比,这种需要在每次请求(call)中发送凭证。

  第三种是OAuth(或者OAuth2)。为第三方的认证所设计,但是更难配置。至少在服务器端更难。

  2、使用Token的方法

  不是在每一次请求时提供用户名和密码的凭证。我们可以让用户通过token交换凭证(we can allow the client to exchange valid credentials for a token),这个token提供用户访问服务器的权限。Token通常比密码更加长而且复杂。比如说,JWTs通常会应对长达150个字符。一旦获得了token,在每次调用API的时候都要附加上它。然后,这仍然比直接发送账户和密码更加安全,哪怕是HTTPS。

  把token想象成一个安全的护照。你在一个安全的前台验证你的身份(通过你的用户名和密码),如果你成功验证了自己,你就可以取得这个。当你走进大楼的时候(试图从调用API获取资源),你会被要求验证你的护照,而不是在前台重新验证。

  3、关于JWTs

  JWTs是一份草案,尽管在本质上它是一个老生常谈的一种更加具体的认证个授权的机制。一个JWT被周期(period)分寸了三个部分。JWT是URL-safe的,意味着可以用来查询字符参数。(译者注:也就是可以脱离URL,不用考虑URL的信息)。

  JWT的第一部分是一个js对象,表面JWT的加密方法。实例使用了HMAC SHA-266

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

  在加密之后,这个对象变成了一个字符串:

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9

  JWT的第二部分是token的核心,他也是一个JS兑现,包含了一些信息。有一些是必须的,有一些是选择性的。一个实例如下:

{"iss":"joe",
"exp":1300819380,
"http://example.com/is_root":true}

  这被称为JWT Claims Set。因为这篇文章的目的,我们将忽视第三个参数。但是你可以阅读这篇文章.这个iss是issuer的简写,表明请求的实体。通常意味着请求API的用户。exp是expires的简写,是用来限制token的生命周期。一旦加密,JSON token就像这样:

eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ

  第三个也是最后一个部分,是JWT根据第一部分和第二部分的签名(Signature)。像这个样子:

dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

  在规范中,有一些选择性的附加属性。有iat表明什么时候token被半吧,nbf去验证在什么时间之前token无效,和aud去指明这个token的收件人是谁。

  处理Tokens我们将用JWT simple模块去处理token,它将使我们从钻研如何加密解密中解脱出来。如果你有兴趣,可以阅读这篇说明,或者读这个仓库的源码。首先我们将使用下面的命令安装这个库。记住你可以在命令中加入--save,让其自动的让其加入到你的package.json文件里面。

npm install jwt-simple

  在你应用的初始环节,加入以下代码。这个代码引入了Express和JWT simple,而且创建了一个新的Express应用。最后一行设定了app的一个名为jwtTokenSecret的变量,其值为‘YOUR_SECRET_STRING’(记得把它换成别的)。

var express=require(‘express‘);varjwt=require(‘jwt-simple‘);
var app=express();app.set(‘jwtTokenSecret‘,‘YOUR_SECRET_STRING‘);

  获取一个Token我们需要做的第一件事就是让客户端通过他们的账号密码交换token。这里有2种可能的方法在RESTful API里面。第一种是使用POST请求来通过验证,使服务端发送带有token的响应。除此之外,你可以使用GET请求,这需要他们使用参数提供凭证(指URL),或者更好的使用请求头。

  这篇文章的目的是为了解释token验证的方法而不是基本的用户名/密码验证机制。所以我们假设我们已经通过请求得到了用户名和密码:

/**

* 验证token

*/

functionauthToken(credentialsRequired) {

returncompose()

.use(function(req,res,next) {

if(req.query && req.query.hasOwnProperty(‘access_token‘)) {

req.headers.authorization=‘Bearer ‘+ req.query.access_token;

}

next();

})

.use(expressJwt({

secret: config.session.secrets,

credentialsRequired:credentialsRequired//是否抛出错误

}))

}

/**

* 验证用户是否登录

*/

functionisAuthenticated() {

returncompose()

.use(authToken(true))

.use(function(err,req,res,next) {

//expressJwt 错误处理中间件

if(err.name===‘UnauthorizedError‘) {

returnres.status(401).send();

}

next();

})

.use(function(req,res,next) {

User.findById(req.user._id,function(err,user) {

if(err)returnres.status(500).send();

if(!user)returnres.status(401).send();

req.user= user;

next();

});

});

}

/**

* 验证用户权限

*/

functionhasRole(roleRequired) {

if(!roleRequired)throw newError(‘Required role needs to be set‘);

returncompose()

.use(isAuthenticated())

.use(functionmeetsRequirements(req,res,next) {

if(config.userRoles.indexOf(req.user.role) >= config.userRoles.indexOf(roleRequired)) {

next();

}

else{

returnres.status(403).send();

}

});

}

  下一步,我们就需要返回JWT token通过一个验证成功的响应。

  注意到jwt.encode()函数有2个参数。第一个就是一个需要加密的对象,第二个是一个加密的密钥。这个token是由我们之前提到的iss和exp组成的。注意到Moment.js被用来设置token将在7天之后失效。而res.json()方法用来传递这个JSON对象给客户端。

原文地址:https://www.cnblogs.com/happy-king/p/8419809.html

时间: 2024-10-27 22:04:06

cookie、session和token的相关文章

Cookie Session 与Token

由于HTTP是一种无状态的协议,服务器端无法知道用户与客户端交互的状态,比如如果一个用于之前已经访问过该服务器,服务器无法知道该用户是第二次访问,Session和Cookie都是用来保存用户与后端服务器的交互状态,简单来说Cookie存储在用户端,而Session存储在服务器端,这种存储方式的不同造成了二者在使用上的巨大区别 由于Cookie在客户端,每次请求的时候都要带着Cookie,如果Cookie非常大且每天的流量很大那么Cookie会占用很大带宽 Session在服务器端,但他只保存在一

关于cookie,session和token

一.理解HTTP“无状态”的含义 我们知道,HTTP是一种无状态的协议,客户端与服务器建立连接并传输数据,数据传输完成后,连接就会关闭. 举个栗子,如果在无状态情况下访问淘宝,会出现以下场景: 1)打开淘宝的url,在这一步输入用户名和密码: 2)在首页选择一样商品,点击进去,又提示需要重新登录.因为HTTP是无状态的,虽然在第1步中已经输入了用户名和密码,但我们的客户端不会记住上一步输入的用户名和密码,而服务器也不会记住已登录的状态: 经过上述例子,我们可以把“无状态”理解为:不会对本次会话设

Cookie,Session和Token机制和区别.

1.背景介绍 由于HTTP是一种无状态协议,服务器没有办法单单从网络连接上面知道访问者的身份,为了解决这个问题,就诞生了Cookie Cookie实际上是一小段的文本信息.客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie 客户端浏览器会把Cookie保存起来.当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器.服务器检查该Cookie, 以此来辨认用户状态.服务器还可以根据需要修改Cookie的内容. 实际就是颁发

存储机制 cookie session jwt token

cookieCookie的诞生 由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的.Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用.比如判断用户是否是第一次访问网站.目前最新的规范是RFC 6265,它是一个由浏览器服务器共同协作实现的规范. Cookie的处理分为: 服务器像客户端发送cookie 浏览器将cookie保存 之后每次http请求浏览器都会将cookie发送给服务器端 session1. 为什么要有session的出现?答:是由于网络中htt

cookie、session与token

一.详述概念 1.Cookie机制 cookie的作用就是为了解决HTTP协议无状态的缺陷.cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的.cookie服务器生成,发送给浏览器,浏览器保存,下次请求同一网站再发送给服务器. cookie的内容主要包括:名字.值.过期时间.路径和域. 路径与域一起构成cookie的作用范围. 若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失.这种生命期为浏览器会话期的cookie被称为会话co

cookie,session,token的定义及区别

参考了很多文章总结的. 1.cookie(储存在用户本地终端上的数据) 服务器生成,发送给浏览器,浏览器保存,下次请求同一网站再发送给服务器. 2.session(会话) a.代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的. b.cookie中存放着一个sessionID.请求时会发送这个ID. c.session因为请求(request对象)而产生. d.session是一个容器,可以存放会话过程中的任何对象. e.session的创建和使用总在服务端,而浏览器从来都没得

cookie session token 之间的区别

cookie 和session的区别 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session. 3.session会在一定时间内保存在服务器上.当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE. 4.单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie. token 和session

Cookie && Session && Token

Cookie的由来: HTTP 本身是一个无状态的 request/response 协议. 服务器接收一个来自客户端的request, 处理完以后返回一个response. 但是这个过程中, 服务器几乎没有什么信息可以用来判定是哪个客户端(用户)发来的request, 也无法记录用户的请求顺序. Cookie是目前识别用户,实现持久会话最好的方式.Cookie通常会跟User-Agent,Referer,X-Forwarded-For,JS等技术共同使用,为服务器提供更为详细的信息.简而言之,

IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动端IM)的数据流交换方式都是Http短连接+TCP或UDP长连接来实现.Http短连接主要用于从服务器读取各种持久化信息:比如用户信息.聊天历史记录.好友列表等等,长连接则是用于实时的聊天消息或指令的接收和发送. 作为IM系统中不可或缺的技术,Http短连的重要性无可替代,但Http作为传统互联网信