首先,web应用程序是使用HTTP协议进行数据传输,因为HTTP协议是无状态的,所以一旦提交数据完成后,客户端和服务器端的连接就会被关闭,再次进行数据的交换就得重新建立新的连接,那么,有个问题就是服务器无法通过连接来跟踪用户的会话。接下来,对于Session和Cookie这个技术就出来了。

简单介绍一下Session和Cookie:

  Session:通过在服务器端记录用户信息从而来确认用户身份,保存在服务器上,每个用户会话都有一个对应的session

  Cookie:通过在客户端记录信息确认身份,客户端浏览器会把Cookie保存起来,当再次访问的时候,把该Cookie一同提交给服务器,就可以进行用户的辨认了

工作时,需要对Tornado的Cookie设置过期时间,然后对于Tornado来说,查看源码得知对Cookie的处理有4个方法。

下面给出4个方法的源码:

  版本说明: Tornado版本为4.4.2

a. get_cookie()

def get_cookie(self, name, default=None):
"""Gets the value of the cookie with the given name, else default."""
if self.request.cookies is not None and name in self.request.cookies:
return self.request.cookies[name].value
return default

可以从源码注释中容易的明白,其为获取cookie的方法,通过给予参数name后拿到cookie的值

b. set_cookie()

def set_cookie(self, name, value, domain=None, expires=None, path="/",
expires_days=None, **kwargs):
"""Sets the given cookie name/value with the given options. Additional keyword arguments are set on the Cookie.Morsel
directly.
See http://docs.python.org/library/cookie.html#morsel-objects
for available attributes.
"""
# The cookie library only accepts type str, in both python 2 and 3
name = escape.native_str(name)
value = escape.native_str(value)
if re.search(r"[\x00-\x20]", name + value):
# Don't let us accidentally inject bad stuff
raise ValueError("Invalid cookie %r: %r" % (name, value))
if not hasattr(self, "_new_cookie"):
self._new_cookie = Cookie.SimpleCookie()
if name in self._new_cookie:
del self._new_cookie[name]
self._new_cookie[name] = value
morsel = self._new_cookie[name]
if domain:
morsel["domain"] = domain
if expires_days is not None and not expires:
expires = datetime.datetime.utcnow() + datetime.timedelta(
days=expires_days)
if expires:
morsel["expires"] = httputil.format_timestamp(expires)
if path:
morsel["path"] = path
for k, v in kwargs.items():
if k == 'max_age':
k = 'max-age' # skip falsy values for httponly and secure flags because
# SimpleCookie sets them regardless
if k in ['httponly', 'secure'] and not v:
continue morsel[k] = v

这个是对Cookie的设置方法,看到expires和expires_days似乎就是我们所要用到的过期时间的设置项

c. get_secure_cookie()

def get_secure_cookie(self, name, value=None, max_age_days=31,
min_version=None):
"""Returns the given signed cookie if it validates, or None. The decoded cookie value is returned as a byte string (unlike
`get_cookie`). .. versionchanged:: 3.2.1 Added the ``min_version`` argument. Introduced cookie version 2;
both versions 1 and 2 are accepted by default.
"""
self.require_setting("cookie_secret", "secure cookies")
if value is None:
value = self.get_cookie(name)
return decode_signed_value(self.application.settings["cookie_secret"],
name, value, max_age_days=max_age_days,
min_version=min_version)

这个get_secure_cookie()也是获取cookie的方法,但是和上面的get_cookie()不同在于这个cookie值是一个加密的字符串,通过加密传输,但是get_cookie()是明文进行传输的,然后还注意到有一个参数 max_age_day=31,这个可以结合下面set_secure_cookie进行理解

d. set_secure_cookie()

def set_secure_cookie(self, name, value, expires_days=30, version=None,
**kwargs):
"""Signs and timestamps a cookie so it cannot be forged. You must specify the ``cookie_secret`` setting in your Application
to use this method. It should be a long, random sequence of bytes
to be used as the HMAC secret for the signature. To read a cookie set with this method, use `get_secure_cookie()`. Note that the ``expires_days`` parameter sets the lifetime of the
cookie in the browser, but is independent of the ``max_age_days``
parameter to `get_secure_cookie`. Secure cookies may contain arbitrary byte values, not just unicode
strings (unlike regular cookies) .. versionchanged:: 3.2.1 Added the ``version`` argument. Introduced cookie version 2
and made it the default.
"""
self.set_cookie(name, self.create_signed_value(name, value,
version=version),
expires_days=expires_days, **kwargs)

通过查看该方法,我们可以发现,其实该方法就是对第一个set_cookie的进一步封装,通过注释可以知道:要使用这个方法对cookie进行设置,必须在项目的Application中,定义一个“cookie_secret” --> 这个cookie_secret应该是随机的,并且长字符串,当然你可以设置成你自己定义的固定的字符串。然后还有一个参数expires_days特别需要值得注意,这里如果我们不进行设置的话,cookie的过期时间将为30天,当然,这个跟get_secure_cookie中的max_age_day是相互独立的。

接下来,我们通过源码分析后,我们想对cookie设置过期时间,只需要在set_secure_cookie()函数中,将expires_day进行重写就可以了。

这里需要注意一下几点,是我在设置过程中踩过的坑,记录下来:

  1.这个设置过期时间的参数 expires_day,如果想以秒作为过期单位的话,应该这样写:expires_day = time.time() + 对应的秒数

  2.如果想设置,关闭浏览器就清楚cookie的话,应该这样设置,将过期时间重写置空:expires_day = None

  3.这个问题,也是我遇到最蛋疼的问题,当时,我设置后,设置关闭浏览器清楚cookie一直无法失效,还一度怀疑是tornado对于chorme浏览器的bug,之后发现了解决办法,请看图:

    

    就是因为chrome这个设置选项,默认是勾选了“关闭浏览器后继续运行后台应用”,所以我每次关闭浏览器打开后cookie永远不会失效。(Ubuntu系统,不同ps去查看系统进程的话根本发现不了没有关闭chrome的进程)

最后总结一下,Session和Cookie在整个项目中具体的设置和开发方法:

两种状态:

  1.对于登陆是会话级别的,就是在系统上面一直有操作的,可以自定义cookie的过期时间

  2.对于客户端来说,选择关闭浏览器就清楚cookie

开发方法:

  1.对于登陆是会话级别,当用户一直有操作的时候,我们不能让cookie直接过期,所以我们在调用set_secure_cookie时,应该设置expires_day=None(关闭浏览器直接过期,如果expires_day后面有过期时间的话,会导致用户在操作途中直接cookie过期而要求重新登陆);

  2.然后,我们如何保持用户在没有操作的一段时间后进行过期呢? 这就要看我们的记录在服务器端的session了,一般我们会把服务器端的session存储在memcache、redis等缓存服务器中,然后设置相应的缓存过期时间,每次当用户在系统上面有操作,有请求发生的时候,我们就重写缓存,重置session的过期时间,当用户一段时间没有操作的时候,存储在缓存中的session就会过期被清除,当用户再次发送请求后发现无法找到对应的session,从而让用户无法进行相应的操作客户端会提示重新登陆。这样子,就可以实现当用户有操作就不过期,没有操作就在一定的时间断内过期要求用户重新登陆了。

Tornado中Cookie过期问题的更多相关文章

  1. Tornado的cookie过期问题

    首先,web应用程序是使用HTTP协议进行数据传输,因为HTTP协议是无状态的,所以一旦提交数据完成后,客户端和服务器端的连接就会被关闭,再次进行数据的交换就得重新建立新的连接,那么,有个问题就是服务 ...

  2. tornado设置cookie过期时间(expires time)

    具体的tornado设置过期时间的东西, 我也是查资料才发现的, 现在就贴代码吧 用户登录之后, 设置cookie, 我使用set_secure_cookie的, 它默认是有个30天的过期时间, 导致 ...

  3. ASP.NET MVC中利用AuthorizeAttribute实现访问身份是否合法以及Cookie过期问题的处理

    话说来到上海已经快半年了,时光如白驹过隙,稍微不注意,时间就溜走了,倒是没有那么忙碌,闲暇之际来博客园还是比较多的,记得上次在逛博问的时候看到有同志在问MVC中Cookie过期后如何作相关处理,他在阐 ...

  4. Tornado中的Cookie设置

    Tornado中的cookie分为两种--普通cookie和安全cookie 普通cookie 1.创建cookie 原型 self.set_cookie(name, value, domain=No ...

  5. web框架详解之tornado 二 cookie

    一.tornado之cookie一 目录: <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  6. servlet中cookie的使用

    ---恢复内容开始--- Cookie是存储在客户端计算机上的文本文件,并保留了它们的各种信息跟踪的目的. Java Servlet透明支持HTTP Cookie. 涉及标识返回用户有三个步骤: 服务 ...

  7. JS中cookie的基本使用

    cookie是本身是HTML中ducument中的一个属性,可以用来保存一些简单的数据信息,比如用户名.密码等,提高一些网站的用户体验度.下面就来简单的说说cookie,它有下面几个特性: 1.有过期 ...

  8. Python中Cookie的处理(一)Cookie库

    Cookie用于服务器实现会话,用户登录及相关功能时进行状态管理.要在用户浏览器上安装cookie,HTTP服务器向HTTP响应添加类似以下内容的HTTP报头: Set-Cookie:session= ...

  9. Laravel5中Cookie的使用

    今天在Laravel框架中使用Cookie的时候,碰到了点问题,自己被迷糊折腾了半多小时.期间研究了Cookie的实现类,也在网站找了许多的资料,包括问答.发现并没有解决问题.网上的答案都是互相抄袭, ...

随机推荐

  1. TCP协议疑难杂症全景解析

    说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人. ...

  2. bind9+mysql dlz(Dynamically Loadable Zones)

    yum install openssl openssl-devel groupadd mysqluseradd -g mysql -s /sbin/nologin -M mysqlchown -R m ...

  3. 【英语魔法俱乐部——读书笔记】 1 初级句型-简单句(Simple Sentences)

    第一部分 1 初级句型-简单句(Simple Sentences):(1.1)基本句型&补语.(1.2)名词短语&冠词.(1.3)动词时态.(1.4)不定式短语.(1.5)动名词.(1 ...

  4. 转: unix实际用户ID和有效用户ID解析

    今天在看APUE,这两个问题很难理解,GOOGLE一下,有篇文章总结的不错,看了一下才明白透彻了. 由于用户在UNIX下经常会遇到 SUID.SGID的概念,而且SUID和SGID涉及到系统安全,所以 ...

  5. navigator对象

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. MES开发学习一

    /*开发批次的当前信息查询界面,显示字段包括批次名,产品名,产品版本,批次数量,开始原因,所有者,当前工序,工艺路线, 工艺路线版本,车间,并能通过批次名,产品名,工序进行过滤和按照批次名正序排列.* ...

  7. 基于Web2.0的RIA框架设计与实现

    http://www.doc88.com/p-8866851533856.html http://cdmd.cnki.com.cn/Article/CDMD-10614-1012472890.htm

  8. java序列化深拷贝

    java深拷贝 序列化和反序列化合成在一起的方法CloneUtils import java.io.ByteArrayInputStream; import java.io.ByteArrayOutp ...

  9. JavaScript 对象、DOM对象、jquery对象的区别、转换详解

    一.JavaScript 对象 JavaScript 提供多个内建对象,比如 String.Date.Array 等等. 对象只是带有属性和方法的特殊数据类型. 访问对象的属性: [javascrip ...

  10. 从SQL下载大量数据到Excel

    之前不知设计原理,发生了大量数据(超过100w行)直接从数据库读取加载到网页中,直接导致内存溢出. Rediculous! 所以,现在改为分页查询到页面中. 由于其有全局逻辑,故折中每次加载1w条数据 ...