Tornado-Secure cookie and Session
这一节涉及的内容有:
1.客户端和服务端操作cookie的方法
2.secure cookie的机制
3.基本/自定义session
文件结构
三个启动文件由下往上对应的分别是三种服务端:使用secure cookie,使用基本的session,使用自定义session。
另外,这一节中的index.html中并任何实质的内容,我只是在里面练习写了一个服务端生成自定义时间的键值对cookie,同样附在下面
Python代码
start.py
from tornado import web
import tornado.ioloop class IndexHandler(web.RequestHandler):
def get(self):
if self.get_argument('user', None) in ['yeff', 'mike']:
self.set_secure_cookie('n', self.get_argument('user'))
self.write('欢迎')
else:
self.write('请登陆') class ManagerHandler(web.RequestHandler):
def get(self):
# 注意这里取得的cookie是bytes格式的,不是字符串格式
if self.get_secure_cookie('n', None) in [b'yeff', b'mike']:
self.write('欢迎登陆: ' + str(self.get_secure_cookie('n'),encoding="utf-8"))
else:
self.redirect('/index') settings = {
"template_path": "views",
"static_path": "static",
"cookie_secret": "salt",
} application = web.Application([
(r"/index", IndexHandler),
(r"/manager", ManagerHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
使用secure cookie的服务端
session-start.py
还有很大的缺陷,如登陆后再装到index还是会提示未登陆。这一点在自定义session中有修正。
from tornado import web
import tornado.ioloop
import time
import hashlib sessions = {} # 可以注意到在用了session后,每次重启客户端后,用户拿着cookie也是没有办法登陆的
# 因为客户端这边的sessions中的内容被清空了,好比用户手里虽然还有钥匙(cookie键值对)
# 但服务端的箱子已经没有了
# 当然sessions可以放在数据库/文件/缓存中,而不是存储在内存中
# cookie是否使用完全看服务端的需求:只要将对应user的islogin信息换成False即可
# 通过在服务端和cookie间多添加一层抽象,既便于存储大量信息,也提升了安全性 class IndexHandler(web.RequestHandler):
def get(self):
if self.get_argument('usn', None) in ['yeff', 'mike']:
_en = hashlib.md5()
_en.update(bytes(str(time.time()), encoding="utf-8"))
user_key = _en.hexdigest()
sessions[user_key] = {}
sessions[user_key]['name'] = 'Yifei Xu'
sessions[user_key]['age'] = ''
sessions[user_key]['accountInfo'] = 'xyfst'
sessions[user_key]['isLogin'] = True
self.set_cookie(name='steam', value=user_key)
self.write('登陆成功了哦@_@')
else:
self.write('请登陆-_-') class ManagerHandler(web.RequestHandler):
def get(self):
user_key = self.get_cookie(name='steam')
user_info = sessions.get(user_key)
if not user_info:
self.redirect("/index")
else:
if user_info.get('isLogin'):
display_str = "Name:%s\tAge:%s\tAccount:%s" % (user_info.get('name'), user_info.get('age'), user_info.get('accountInfo'))
self.write(display_str)
else:
self.write("登陆信息已失效,得重新登陆啦*_*") settings = {
"template_path": "views",
"static_path": "static",
} application = web.Application([
(r"/index", IndexHandler),
(r"/manager", ManagerHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
使用基本session的服务端
class-session-start.py
from tornado import web
import tornado.ioloop SESSIONS = {} class Sessions(object):
def __init__(self, handler, cookie_key):
self.handler = handler
self.user_key = None
self.cookie_key = cookie_key @staticmethod
def generate_random_str():
import hashlib, time
_en = hashlib.md5()
_en.update(bytes(str(time.time()), encoding="utf-8"))
return _en.hexdigest() def __setitem__(self, k, v):
# 创建随机字符串
# 创建自己的箱子
# 在箱子中放入信息对
# 在客户端中放入箱子的钥匙 # 如果服务端还没有钥匙,先制作一个钥匙,并创建一个对应的箱子
if not SESSIONS.get(self.user_key):
self.user_key = Sessions.generate_random_str()
SESSIONS[self.user_key] = {}
# 起初/manager页面无论如何都无法进入,想了很久
# 这个点费了我不少时间才找到:这边对SESSIONS中是否存在钥匙没有判断,使得每次set方法清空钥匙对应的箱子
SESSIONS[self.user_key][k] = v
self.handler.set_cookie(self.cookie_key, self.user_key) def __getitem__(self, item):
# 获取客户端递来的钥匙
# 看看房间里有对应钥匙吗
# 用钥匙打开箱子,获得信息对,取出值
# 没有钥匙返回None
value = None
_user_key = self.handler.get_cookie(self.cookie_key)
if SESSIONS.get(_user_key):
self.user_key = _user_key
value = SESSIONS[self.user_key][item]
return value # IndexHandler和ManagerHandler都继承这个类
# tornado为我们留的钩子,使用继承RequestHandler的类并初始化时(执行__init__方法),会在最后执行 self.initialize(**kwargs)
# 我们可以自己定义initialize的函数内容,以实现不同的效果
# 这里我们是初始化了服务端的Sessions类,继承之后,两个类就不用自己再初始化了,更简洁一些
class BaseHandler(web.RequestHandler):
def initialize(self):
self.session = Sessions(self, 'steam') # tornado内部通过反射调用get和post方法
# obj = IndexxHandler()
# func = getattr(obj, "get")
# func()
class IndexHandler(BaseHandler):
def get(self):
# 如果客户端有对应的钥匙则转到manager页面尝试匹配
if SESSIONS.get(self.get_cookie('steam')):
self.redirect('/manager')
# 注意这里的多层嵌套
# 第一次我将两个if写在了同级,但在执行了redirect函数后,还是会接着执行下面判断中的else块
# 虽不至于中止程序,但会报错,所以这里写成了两层嵌套
else:
# 判断用户登陆信息是否正确(这里作了简化,只判断了用户名)
if self.get_argument('usn', None) in ['yeff', 'mike']:
# session = Sessions(self, 'steam')
self.session['isLogin'] = True
self.session['name'] = 'Yifei Xu'
self.session['age'] = ''
self.session['accountInfo'] = 'xyfst'
self.write('登陆成功了哦@_@')
else:
self.write('请先登陆呦') class ManagerHandler(BaseHandler):
def get(self):
# session = Sessions(self, 'steam') # 从客户端拿来钥匙
# 看看服务端的房间里有钥匙吗
# 有则取出对应的信息对
_site_user_key = self.get_cookie(self.session.cookie_key)
if not SESSIONS.get(_site_user_key):
self.write('登陆信息已失效,请先登陆*。*')
else:
display_str = "Name:%s\tAge:%s\tAccount:%s" % (self.session['name'], self.session['age'], self.session['accountInfo'])
self.write(display_str) settings = {
"template_path": "views",
"static_path": "static",
} application = web.Application([
(r"/index", IndexHandler),
(r"/manager", ManagerHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
使用自定义session的服务端
HTML代码
index.html
并没有实质的实际内容,内部只有一个我自己写的生成自定义cookie的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Cookie</h1>
<script>
<!--根据用户输入设置cookie,时间单位可以是yMdhms,格式是数字+对应字母-->
<!--也可以针对不同单位的时间分开写方法,我这里整合为了一种方法,顺便复习了js的字符串操作方法以及switch语法-->
function setCookie(name,value,expires){
var current_date = new Date();
if(typeof(expires) == 'string'){
var unit = expires.charAt(expires.length-1);
var str_num = expires.slice(0,expires.length-1);
var num = parseInt(str_num);
if('yMdhms'.includes(unit) && num){
switch(unit){
case 'y':
current_date.setDate(current_date.getDate() + num * 365);
case 'M':
current_date.setDate(current_date.getDate() + num * 30);
case 'd':
current_date.setDate(current_date.getDate() + num);
case 'h':
current_date.setSeconds(current_date.getSeconds() + num * 60 * 60);
case 'm':
current_date.setSeconds(current_date.getSeconds() + num * 60);
case 's':
current_date.setSeconds(current_date.getSeconds() + num);
}
}else{
return false;
}
}else{
return false;
}
document.cookie = name + "=" + value + ";expires=" + current_date.toUTCString();
return true;
} </script>
</body>
</html>
浏览器端生成自定义cokie
额外内容
这一节也涉及到了python类的特殊方法以及钩子函数,在注释里都有讲到,下面也附带一些解释。
class Foo:
def __call__(self, *args, **kwargs):
pass def __init__(self):
pass def __class__(self):
pass def __setitem__(self, key, value):
pass def __getitem__(self, item):
pass def __delitem__(self, key):
pass obj = Foo() # __call__, __init__
obj['k1'] = 'v1' # __setitem__
obj['k1'] # __getitem__
del obj['k1'] # __delitem__
钩子函数: http://blog.csdn.net/sunstars2009918/article/details/39340449(这位作者讲的很清晰,虽然例子是C。*-*)
Tornado-Secure cookie and Session的更多相关文章
- tornado 09 cookie和session
tornado 09 cookie和session 一.cookie #有什么办法能够让浏览器记住登录信息,下次再打开的时候可以自动登录?网站是如何记录登录信息的? class SetCookieHa ...
- web框架--tornado之cookie与session初识
cookie的本质其实就是在浏览器端保存的键值对, 每当浏览器端发送一次请求, 都会将这些键值对附加在请求中并发送给服务器端. 一.目录结构 二.main_pro.py #!/usr/bin/env ...
- Django实现表单验证、CSRF、cookie和session、缓存、数据库多表操作(双下划綫)
通常验证用户输入是否合法的话,是前端js和后端共同验证的,这是因为前端js是可以被禁用的,假如被禁用了,那就没法用js实现验证合法与否了,也就是即使用户输入的不合法,但是也没提示,用户也不知道怎么输入 ...
- Tornado中Cookie过期问题
首先,web应用程序是使用HTTP协议进行数据传输,因为HTTP协议是无状态的,所以一旦提交数据完成后,客户端和服务器端的连接就会被关闭,再次进行数据的交换就得重新建立新的连接,那么,有个问题就是服务 ...
- Django之Cookie、Session、CSRF、Admin
Django之Cookie.Session.CSRF.Admin Cookie 1.获取Cookie: 1 2 3 4 5 6 request.COOKIES['key'] request.get ...
- Tornado的cookie过期问题
首先,web应用程序是使用HTTP协议进行数据传输,因为HTTP协议是无状态的,所以一旦提交数据完成后,客户端和服务器端的连接就会被关闭,再次进行数据的交换就得重新建立新的连接,那么,有个问题就是服务 ...
- Django详解之四、cookie和session
一.使用背景 思路 简单的后台管理:对人员的管理 1. 登录注册 2. 老师 班级管理 学院管理 3. 增删改查 开发: 1. 定义数据库表结构 a) 表结构关系 i. class classes(m ...
- django的cookie和session以及内置信号、缓存
cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...
- 【转】Cookie和Session区别和联系详解
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...
随机推荐
- 关于学习Linux的基本命令操作
常用的Linux 命令 scp root/1.txt root@127.0.0.1:/home rpm 安装软件 systemctl start service 启动服务 systemctl res ...
- [再寄小读者之数学篇](2014-06-20 求极限-H\"older 不等式的应用)
设非负严格增加函数 $f$ 在区间 $[a,b]$ 上连续, 有积分中值定理, 对于每个 $p>0$ 存在唯一的 $x_p\in (a,b)$, 使 $$\bex f^p(x_p)=\cfrac ...
- [物理学与PDEs]第5章习题5 超弹性材料中客观性假设的贮能函数表达
设超弹性材料的贮能函数 $\hat W$ 满足 (4. 19) 式, 证明由它决定的 Cauchy 应力张量 ${\bf T}$ 满足各向同性假设 (4. 7) 式. 证明: 若贮能函数 $W$ 满足 ...
- RT-SA-2019-007 Code Execution via Insecure Shell Functiongetopt_simple
Advisory: Code Execution via Insecure Shell Function getopt_simple RedTeam Pentesting discovered tha ...
- Yii2.0连接多个数据库
Yii2.0连接多个数据库 一个项目根据需要会要求连接多个数据库,这里记录下实际项目中的操作流程.包括对数据库连接的配置以及如何生成模型文件,在控制器中加以运用. 一.配置 打开数据库配置文件c ...
- 通过IDEA搭建scala开发环境开发spark应用程序
一.idea社区版安装scala插件 因为idea默认不支持scala开发环境,所以当需要使用idea搭建scala开发环境时,首先需要安装scala插件,具体安装办法如下. 1.打开idea,点击c ...
- 408 JavaScript 变量、数据类型、正则
JavaScript 特点 是一门解释性脚本语言 .基于对象脚本编程.简单性(弱类型).安全性.动态性.跨平台 作用: 初学js 引入方式 与html有相同之处 也是3种1 用JavaScript前缀 ...
- linux异步IO的两种方式【转】
转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...
- Linux命令行下编辑常用的快捷键
Linux命令行编辑快捷键: Ctrl+r 然后输入若干字符,开始向上搜索包含该字符的命令,继续按Ctrl+r,搜索上一条匹配的命令,按Ctrl+c或上下键退出. Ctrl+l 清屏 !num 执行命 ...
- javaWeb之使用servlet搭建服务器入门
servlet: 百度百科说法: Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,主要功能在于交互式地浏览和修改 ...