cookie、session与token之间的关系


cookie、session与token之间的关系


token
令牌,是用户身份的验证方式。
最简单的token组成:uid(用户惟一的身份标识)、time(当前时间的时间戳)、sign(签名)。
对Token认证的五点认识javascript

  • 一个Token就是一些信息的集合;
  • 在Token中包含足够多的信息,以便在后续请求中减小查询数据库的概率;
  • 服务端须要对cookie和HTTP Authrorization Header进行Token信息的检查;
  • 基于上一点,你能够用一套token认证代码来面对浏览器类客户端和非浏览器类客户端;
  • 由于token是被签名的,因此咱们能够认为一个能够解码认证经过的token是由咱们系统发放的,其中带的信息是合法有效的;

 

session
会话,表明服务器与浏览器的一次会话过程,这个过程是连续的,也能够时断时续。
cookie中存放着一个sessionID,请求时会发送这个ID;
session由于请求(request对象)而产生;
session是一个容器,能够存放会话过程当中的任何对象;
session的建立与使用老是在服务端,浏览器历来都没有获得过session对象;
session是一种http存储机制,目的是为武装的http提供持久机制。html

cookie
储存在用户本地终端上的数据,服务器生成,发送给浏览器,下次请求统一网站给服务器。java

cookie与session区别
cookie数据存放在客户端上,session数据放在服务器上;
cookie不是很安全,且保存数据有限;
session必定时间内保存在服务器上,当访问增多,占用服务器性能。node

session与token
做为身份认证,token安全行比session好;
Session 认证只是简单的把User 信息存储到Session 里,由于SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 而Token ,若是指的是OAuth Token 或相似的机制的话,提供的是 认证 和 受权 ,认证是针对用户,受权是针对App 。其目的是让 某App有权利访问 某用户 的信息。git

token与cookie
Cookie是不容许垮域访问的,可是token是支持的, 前提是传输的用户认证信息经过HTTP头传输;github

token就是令牌,好比你受权(登陆)一个程序时,他就是个依据,判断你是否已经受权该软件;cookie就是写在客户端的一个txt文件,里面包括你登陆信息之类的,这样你下次在登陆某个网站,就会自动调用cookie自动登陆用户名;session和cookie差很少,只是session是写在服务器端的文件,也须要在客户端写入cookie文件,可是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。web

HTTP协议与状态保持:Http是一个无状态协议算法

 

1. 实现状态保持的方案:数据库

1)修改Http协议,使得它支持状态保持(难作到)express

2)Cookies:经过客户端来保持状态信息

Cookie是服务器发给客户端的特殊信息

cookie是以文本的方式保存在客户端,每次请求时都带上它

3)Session:经过服务器端来保持状态信息

Session是服务器和客户端之间的一系列的交互动做

服务器为每一个客户端开辟内存空间,从而保持状态信息

因为须要客户端也要持有一个标识(id),所以,也要求服务器端和客户端传输该标识,

标识(id)能够借助Cookie机制或者其余的途径来保存

2. COOKIE机制

1)Cookie的基本特色

Cookie保存在客户端

只能保存字符串对象,不能保存对象类型

须要客户端浏览器的支持:客户端能够不支持,浏览器用户可能会禁用Cookie

2)采用Cookie须要解决的问题

Cookie的建立

一般是在服务器端建立的(固然也能够经过javascript来建立)

服务器经过在http的响应头加上特殊的指示,那么浏览器在读取这个指示后就会生成相应的cookie了

Cookie存放的内容

业务信息("key","value")

过时时间

域和路径

浏览器是如何经过Cookie和服务器通讯?

经过请求与响应,cookie在服务器和客户端之间传递

每次请求和响应都把cookie信息加载到响应头中;依靠cookie的key传递。

3. COOKIE编程

1)Cookie类

Servlet API封装了一个类:javax.servlet.http.Cookie,封装了对Cookie的操做,包括:

public Cookie(String name, String value) //构造方法,用来建立一个Cookie

HttpServletRequest.getCookies() //从Http请求中能够获取Cookies

HttpServletResponse.addCookie(Cookie) //往Http响应添加Cookie

public int getMaxAge() //获取Cookie的过时时间值

public void setMaxAge(int expiry) //设置Cookie的过时时间值

2)Cookie的建立

Cookie是一个名值对(key=value),并且无论是key仍是value都是字符串

如: Cookie visit = new Cookie("visit", "1");

3)Cookie的类型——过时时间

会话Cookie

Cookie.setMaxAge(-1);//负整数

保存在浏览器的内存中,也就是说关闭了浏览器,cookie就会丢失

普通cookie

Cookie.setMaxAge(60);//正整数,单位是秒

表示浏览器在1分钟内不继续访问服务器,Cookie就会被过期失效并销毁(一般保存在文件中)

注意:

cookie.setMaxAge(0);//等价于不支持Cookie;

 

4. SESSION机制

每次客户端发送请求,服务断都检查是否含有sessionId。

若是有,则根据sessionId检索出session并处理;若是没有,则建立一个session,并绑定一个不重复的sessionId。

1)基本特色

状态信息保存在服务器端。这意味着安全性更高

经过相似与Hashtable的数据结构来保存

能支持任何类型的对象(session中可含有多个对象)

2)保存会话id的技术(1)

Cookie

这是默认的方式,在客户端与服务器端传递JSeesionId

缺点:客户端可能禁用Cookie

表单隐藏字段

在被传递回客户端以前,在 form 里面加入一个hidden域,设置JSeesionId:

<input type=hidden name=jsessionid value="3948E432F90932A549D34532EE2394" />

URL重写

直接在URL后附加上session id的信息

HttpServletResponse对象中,提供了以下的方法:

encodeURL(url); //url为相对路径

5. SESSION编程

1)HttpSession接口

Servlet API定义了接口:javax.servlet.http.HttpSession, Servlet容器必须实现它,用以跟踪状态。

当浏览器与Servlet容器创建一个http会话时,容器就会经过此接口自动产生一个HttpSession对象

2)获取Session

HttpServletRequest对象获取session,返回HttpSession:

request.getSession(); //表示若是session对象不存在,就建立一个新的会话

request.getSession(true); //等价于上面这句;若是session对象不存在,就建立一个新的会话

request.getSession(false); //表示若是session对象不存在就返回 null,不会建立新的会话对象

3)Session存取信息

session.setAttribute(String name,Object o) //往session中保存信息

Object session.getAttribute(String name) //从session对象中根据名字获取信息

4)设置Session的有效时间

public void setMaxInactiveInterval(int interval)

设置最大非活动时间间隔,单位秒;

若是参数interval是负值,表示永不过期。零则是不支持session。

经过配置web.xml来设置会话超时,单位是分钟

<seesion-config>

<session-timeout>1</session-timeout>

</session-config>

容许两种方式并存,但前者优先级更高

5)其余经常使用的API

HttpSession.invalidate() //手工销毁Session

boolean HttpSession.isNew() //判断Session是否新建

若是是true,表示服务器已经建立了该session,但客户端尚未加入(尚未创建会话的握手)

HttpSession.getId() //获取session的id

6). 两种状态跟踪机制的比较

Cookie Session

保持在客户端 保存在服务器端

只能保持字符串对象 支持各类类型对象

经过过时时间值区分Cookie的类型 须要sessionid来维护与客户端的通讯

会话Cookie——负数 Cookie(默认)

普通Cookie——正数 表单隐藏字段

不支持Cookie——0 url重写

 

 

JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案

1、跨域认证的问题

互联网服务离不开用户认证。通常流程是下面这样。

一、用户向服务器发送用户名和密码。

二、服务器验证经过后,在当前对话(session)里面保存相关数据,好比用户角色、登陆时间等等。

三、服务器向用户返回一个 session_id,写入用户的 Cookie。

四、用户随后的每一次请求,都会经过 Cookie,将 session_id 传回服务器。

五、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。

这种模式的问题在于,扩展性(scaling)很差。单机固然没有问题,若是是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都可以读取 session。

举例来讲,A 网站和 B 网站是同一家公司的关联服务。如今要求,用户只要在其中一个网站登陆,再访问另外一个网站就会自动登陆,请问怎么实现?

一种解决方案是 session 数据持久化,写入数据库或别的持久层。各类服务收到请求后,都向持久层请求数据。这种方案的优势是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

另外一种方案是服务器索性不保存 session 数据了,全部数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个表明。

2、JWT 的原理

JWT 的原理是,服务器认证之后,生成一个 JSON 对象,发回给用户,就像下面这样。

{
  "姓名": "张三",
  "角色": "管理员",
  "到期时间": "2018年7月1日0点0分"
}

之后,用户与服务端通讯的时候,都要发回这个 JSON 对象。服务器彻底只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名(详见后文)。

服务器就不保存任何 session 数据了,也就是说,服务器变成无状态了,从而比较容易实现扩展。

3、JWT 的数据结构

实际的 JWT 大概就像下面这样。

它是一个很长的字符串,中间用点(.)分隔成三个部分。注意,JWT 内部是没有换行的,这里只是为了便于展现,将它写成了几行。

JWT 的三个部分依次以下。

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

写成一行,就是下面的样子。

Header.Payload.Signature

下面依次介绍这三个部分。

3.1 Header

Header 部分是一个 JSON 对象,描述 JWT 的元数据,一般是下面的样子。

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

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。

3.2 Payload

Payload 部分也是一个 JSON 对象,用来存放实际须要传递的数据。JWT 规定了7个官方字段,供选用。

  • iss (issuer):签发人
  • exp (expiration time):过时时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你还能够在这个部分定义私有字段,下面就是一个例子。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

注意,JWT 默认是不加密的,任何人均可以读到,因此不要把秘密信息放在这个部分。

这个 JSON 对象也要使用 Base64URL 算法转成字符串。

3.3 Signature

Signature 部分是对前两部分的签名,防止数据篡改。

首先,须要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。而后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

算出签名之后,把 Header、Payload、Signature 三个部分拼成一个字符串,每一个部分之间用"点"(.)分隔,就能够返回给用户。

3.4 Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本相似,但有一些小的不一样。

JWT 做为一个令牌(token),有些场合可能会放到 URL(好比 api.example.com/?token=xxx)。Base64 有三个字符+/=,在 URL 里面有特殊含义,因此要被替换掉:=被省略、+替换成-/替换成_ 。这就是 Base64URL 算法。

4、JWT 的使用方式

客户端收到服务器返回的 JWT,能够储存在 Cookie 里面,也能够储存在 localStorage。

此后,客户端每次与服务器通讯,都要带上这个 JWT。你能够把它放在 Cookie 里面自动发送,可是这样不能跨域,因此更好的作法是放在 HTTP 请求的头信息Authorization字段里面。

Authorization: Bearer <token>

另外一种作法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

5、JWT 的几个特色

(1)JWT 默认是不加密,但也是能够加密的。生成原始 Token 之后,能够用密钥再加密一次。

(2)JWT 不加密的状况下,不能将秘密数据写入 JWT。

(3)JWT 不只能够用于认证,也能够用于交换信息。有效使用 JWT,能够下降服务器查询数据库的次数。

(4)JWT 的最大缺点是,因为服务器不保存 session 状态,所以没法在使用过程当中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期以前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 自己包含了认证信息,一旦泄露,任何人均可以得到该令牌的全部权限。为了减小盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减小盗用,JWT 不该该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

6、参考连接