1 Cookie和Session
Cookie和Session都为了用来保存状态信息,都是保存客户端状态的机制,它们都是为了解决HTTP无状态的问题而所做的努力。
Session可以用Cookie来实现,也可以用URL回写的机制来实现。用Cookie来实现的Session可以认为是对Cookie更高级的应用。
1.1两者比较
Cookie和Session有以下明显的不同点:
1)Cookie将状态保存在客户端,Session将状态保存在服务器端;
2)Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器。Cookie最早在RFC2109中实现,后续RFC2965做了增强。网络服务器用HTTP头向客户端发送cookies,在客户终端,浏览器解析这些cookies并将它们保存为一个本地文件,它会自动将同一服务器的任何请求缚上这些cookies。Session并没有在HTTP的协议中定义;
3)Session是针对每一个用户的,变量的值保存在服务器上,用一个sessionID来区分是哪个用户session变量,这个值是通过用户的浏览器在访问的时候返回给服务器,当客户禁用cookie时,这个值也可能设置为由get来返回给服务器;
4)就安全性来说:当你访问一个使用session 的站点,同时在自己机子上建立一个cookie,建议在服务器端的SESSION机制更安全些.因为它不会任意读取客户存储的信息。
1.2 Session机制
Session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为 session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个 session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个 session id将被在本次响应中返回给客户端保存。
1.2.1 Session的实现方式
1 使用Cookie来实现
服务器给每个Session分配一个唯一的JSESSIONID,并通过Cookie发送给客户端。
当客户端发起新的请求的时候,将在Cookie头中携带这个JSESSIONID。这样服务器能够找到这个客户端对应的Session。
流程如下图所示:
2 使用URL回显来实现
URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带会服务器。
如果直接在浏览器输入服务端资源的url来请求该资源,那么Session是匹配不到的。
Tomcat对Session的实现,是一开始同时使用Cookie和URL回写机制,如果发现客户端支持Cookie,就继续使用Cookie,停止使用URL回写。如果发现Cookie被禁用,就一直使用URL回写。jsp开发处理到Session的时候,对页面中的链接记得使用response.encodeURL() 。
1.2.2 与Cookie相关的HTTP扩展头
1)Cookie:客户端将服务器设置的Cookie返回到服务器;
2)Set-Cookie:服务器向客户端设置Cookie;
3)Cookie2 (RFC2965)):客户端指示服务器支持Cookie的版本;
4)Set-Cookie2 (RFC2965):服务器向客户端设置Cookie。
1.2.3 Cookie的流程
服务器在响应消息中用Set-Cookie头将Cookie的内容回送给客户端,客户端在新的请求中将相同的内容携带在Cookie头中发送给服务器。从而实现会话的保持。
流程如下图所示:
2 缓存的实现原理
2.1 什么是Web缓存
WEB缓存(cache)位于Web服务器和客户端之间。
缓存会根据请求保存输出内容的副本,例如html页面,图片,文件,当下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访问请求,而不是向源服务器再次发送请求。
HTTP协议定义了相关的消息头来使WEB缓存尽可能好的工作。
2.2缓存的优点
减少相应延迟:因为请求从缓存服务器(离客户端更近)而不是源服务器被相应,这个过程耗时更少,让web服务器看上去相应更快。
减少网络带宽消耗:当副本被重用时会减低客户端的带宽消耗;客户可以节省带宽费用,控制带宽的需求的增长并更易于管理。
2.3与缓存相关的HTTP扩展消息头
Expires:指示响应内容过期的时间,格林威治时间GMT
Cache-Control:更细致的控制缓存的内容
Last-Modified:响应中资源最后一次修改的时间
ETag:响应中资源的校验值,在服务器上某个时段是唯一标识的。
Date:服务器的时间
If-Modified-Since:客户端存取的该资源最后一次修改的时间,同Last-Modified。
If-None-Match:客户端存取的该资源的检验值,同ETag。
2.4客户端缓存生效的常见流程
服务器收到请求时,会在200OK中回送该资源的Last-Modified和ETag头,客户端将该资源保存在cache中,并记录这两个属性。当客户端需要发送相同的请求时,会在请求中携带If-Modified-Since和If-None-Match两个头。两个头的值分别是响应中Last-Modified和ETag头的值。服务器通过这两个头判断本地资源未发生变化,客户端不需要重新下载,返回304响应。常见流程如下图所示:
2.5 Web缓存机制
HTTP/1.1中缓存的目的是为了在很多情况下减少发送请求,同时在许多情况下可以不需要发送完整响应。前者减少了网络回路的数量;HTTP利用一个“过期(expiration)”机制来为此目的。后者减少了网络应用的带宽;HTTP用“验证(validation)”机制来为此目的。
HTTP定义了3种缓存机制:
1)Freshness:允许一个回应消息可以在源服务器不被重新检查,并且可以由服务器和客户端来控制。例如,Expires回应头给了一个文档不可用的时间。Cache-Control中的max-age标识指明了缓存的最长时间;
2)Validation:用来检查以一个缓存的回应是否仍然可用。例如,如果一个回应有一个Last-Modified回应头,缓存能够使用If-Modified-Since来判断是否已改变,以便判断根据情况发送请求;
3)Invalidation: 在另一个请求通过缓存的时候,常常有一个副作用。例如,如果一个URL关联到一个缓存回应,但是其后跟着POST、PUT和DELETE的请求的话,缓存就会过期。
***********************************************************************************************************************************************************************************************************************************************************************************************
cookie的存储
cookie是浏览器支持的一种本地存储方式。以dict,键值对方式存储。
1
|
{
"sessionkey"
:
"123"
}
|
浏览器会自动对于它进行解析。
http请求是一种无状态的请求
用户向服务器发起的两次请求之间是没有状态的。也就是服务器并不知道这是同一个用户发的。
有状态请求(cookie)
服务器a
发回来的id
会放到服务器a
的域之下。不能跨域访问cookie。
使用浏览器随便打开一个网页,然后f12
打开。
比如我使用的Chrome
浏览器
会找到存储在浏览器本地的cookie值
点击clear all
清空所有的cookie
f5
刷新页面,会发现又把这些cookie值进来。
如果将用户名和密码直接保存在cookie,可以实现最垃圾最简略版本的自动登录。
解决cookie放在本地不安全的问题(session)
用户在第一次请求后,浏览器回复的id既可以是用户的user id。
也可以一段任意的字符串,我们把它叫做session id
根据用户名和密码,服务器会采用自己的规则生成session id
。这个session id
保存在本地cookie。浏览器请求服务器会携带。
1
2
3
|
输入用户名 & 密码
调用 login(), 后端程序会根据用户名密码生成session id。保存在数据库中。
用户登录之后,需要通过这个session id取出这些基本信息。
|
Django的默认表中的session
表就记录了用户登录时,后端我们Django为用户生成的sessionid
。
可以看到session key value
和过期时间。
我们可以清空这张表的数据。运行项目进行登录。
此时通过f12
查看浏览器在本地存储的session id
。可以看到如下图和我们数据库中的一致。
session_key 发到浏览器叫做session id
通过session id 用户访问任何一个页面都会携带,服务器就会认识。
Setting.py中,
这个app会拦截我们每次的request请求,在request
中找到session id,然后去数据表中进行查询。
然后通过session key
去找到session data
。此时直接为我们取出了user。
在服务器返回浏览器的response
中也会直接加上session id
cookie是浏览器本地存储机制,存在域名之下,存储不安全。
服务器在返回id时通过规则生成一串字符,并设置了过期时间。存储在服务器端(数据库)
http是无状态的网络协议,请求响应后,断开了TCP连接,下一次连接与上一次无关。为了识别不同的请求是否来自同一客户,引用HTTP会话机制,而维持这个会话则主要靠session和cookie。简单来说,cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
一、cookie
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了,而这个通行证就是cookie了。Cookie实际上是一小段的文本信息,存储在客户端,Web服务器通过传送HTTP 包头中的Set-Cookie 消息把一个cookie发送到用户的浏览器中,内容主要包括:名字,值,过期时间,路径和域,路径与域一起构成cookie的作用范围果不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的 cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器 就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。
二、session
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构来保存信息,一般存储在文件、数据库或内存中。当客户端第一次请求服务端的时候,服务端会检查客户端的请求是否包含sessionid,如果有的话则会检索这个sessionid对应的session是否存在,如果不存在则会创建相应的会话信息,生成对应的session,并将sessionid返回给客户端,客户端接收到这个sessionid,把它存储起来,下一次发送请求的时候,附带着这个session一起发送给服务端,服务端只要根据这个sessionid,就知道是谁了,而这个sessionid就是这次会话生命周期的凭证,服务端可以给这个sessionid设置过期时间,一但客户端丢失这个sessionid或者是服务端认为这个sessionid失效了,那么这次会话就结束了。
三、如何保持登录状态
1、session
使用session保持登录状态是相对安全的一种方式,但是session保持的会话一般都是很短暂的,并且关闭浏览器也会销毁session,这样就会导致用户登录状态频繁丢失,适用于用户验证严格的系统。
2、cookies
使用cookie在客户端保存用户信息(不建议保存用户密码,即使进行加密)来达到保持登录状态也是常用的一种办法,可以达到长期保持登录状态,但是不可否认的是这种方式不太安全,容易被伪造,我们能做的就是去尽量提高伪造的难度,例如对cookie的内容进行加密,传到服务端再进行解密或校验。
3、token
然而某些浏览器禁用了cookie或者是app应用呢,此时可以采用token机制。token机制就是当用户登录成功的时候服务端采用算法生成一串字符串,保存在数据库,并设置过期时间然后返回给客户端,客户端拿到这个token在以后多的每次请求时带上这个token,服务端接收到这个token会进行验证,如果校验通过则认为该用户是处于登录状态的,否则返回未登录异常,客户端再次跳转到登录页面。然而有人会问,如果这个token被盗取了那别人不就可以伪装这个用户为所欲为了吗,我们可以引入一个secret的概念,一个用户id对应一个secret,这个secret客户端和服务端都需要知道,客户端接收到token后将token和secret一起进行可逆加密,生成一串字符串,然后把该字符串连同用户id一起传给服务端,服务端接收到后拿用户id去数据库检索secret,和服务端采用一样的加密算法将token和该secret进行加密,与客户端传过来的字符串进行比较,如果一致的话则证明该用户是有效的。由于黑客无法知道这个secret,所以就算知道了token他也无可奈何。
链接:https://www.jianshu.com/p/83f48ba6b1ff
token详解以及应用原理
一、我们先解释一下Token的含义
1、Token的引入:
Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
2、Token的定义:
Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
3、使用Token的目的:
Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
4.Token 的优点:
扩展性更强,也更安全点,非常适合用在 Web 应用或者移动应用上。Token 的中文有人翻译成 “令牌”,我觉得挺好,意思就是,你拿着这个令牌,才能过一些关卡。
5.Token一般用在三个地方:
①防止表单重复提交
②anti csrf攻击(跨站点请求伪造)
③身份验证(单点登录)
了解了Token的意义后,我们就更明确的知道为什么要用他了。
二、如何使用Token?
这是本文的重点,在这里我就介绍常用的两种方式。
1、用设备号/设备mac地址作为Token(推荐)
客户端:客户端在登录的时候获取设备的设备号/mac地址,并将其作为参数传递到服务端。
服务端:服务端接收到该参数后,便用一个变量来接收同时将其作为Token保存在数据库,并将该Token设置到session中,客户端每次请求的时候都要统一拦截,并将客户端传递的token和服务器端session中的token进行对比,如果相同则放行,不同则拒绝。 分析:此刻客户端和服务器端就统一了一个唯一的标识Token,而且保证了每一个设备拥有了一个唯一的会话。该方法的缺点是客户端需要带设备号/mac地址作为参数传递,而且服务器端还需要保存;优点是客户端不需重新登录,只要登录一次以后一直可以使用,至于超时的问题是有服务器这边来处理,如何处理?若服务器的Token超时后,服务器只需将客户端传递的Token向数据库中查询,同时并赋值给变量Token,如此,Token的超时又重新计时。
2、用session值作为Token
客户端:客户端只需携带用户名和密码登陆即可。
客户端:客户端接收到用户名和密码后并判断,如果正确了就将本地获取sessionID作为Token返回给客户端,客户端以后只需带上请求数据即可。
分析:这种方式使用的好处是方便,不用存储数据,但是缺点就是当session过期后,客户端必须重新登录才能进行访问数据。
三、使用过程中出现的问题以及解决方案?
刚才我们轻松介绍了Token的两种使用方式,但是在使用过程中我们还出现各种问题,Token第一种方法中我们隐藏了一个在网络不好或者并发请求时会导致多次重复提交数据的问题。
该问题的解决方案:将session和Token套用,如此便可解决,如何套用呢?请看这段解释:
session是一个在单个操作人员整个操作过程中,与服务端保持通信的唯一识别信息。在同一操作人员的多次请求中,session始终保证是同一个对象,而不是多个对象,因为可以对其加锁。当同一操作人员多个请求进入时,可以通过session限制只能单向通行
本文正是通过使用session以及在session中加入token,来验证同一个操作人员是否进行了并发重复的请求,在后一个请求到来时,使用session中的token验证请求中的token是否一致,当不一致时,被认为是重复提交,将不准许通过。
这就是解决重复提交的方案。
四、基于 Token 的身份验证方法
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
问题:session和cookie都能实现免登录,所以即使在访问服务端的时候不带sessionid,那还有cookie啊,cookie里的用户名和密码提交给服务端也是可以实现免登录的呀, 尽管不安全.通过sessionid去数据库获取用户信息当然也可以,但是当两者同时存在时,会存在一个优先级关系吗?加上一个token呢?只要其中一个其作用即可还是要两个三个 都匹配?