跨站请求伪造CSRF

开启xsrf(就是叫法不一样和csrf一样),'xsrf_cookies':True

settings = {
'template_path':'template',
'static_path':'static',
'static_path_prefix':'/static/',
'xsrf_cookies':True,
}

在post表单中增加csrf认证

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>index.html</h1>
<h1>{{ name }}</h1>
<form action="/index" method="post">
{% module xsrf_form_html() %}
<p>user:<input type="text"/></p>
<p>password:<input type="password" /> </p>
<input type="submit" value="submit" />
</form>
</body>
</html>

网站请求效果(表单中没有增加认证token):

加上token

AJAX方法

官方提供:

获取cookie的token信息  args._xsrf = getCookie("_xsrf");
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
} jQuery.postJSON = function(url, args, callback) {
args._xsrf = getCookie("_xsrf");
$.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
success: function(response) {
callback(eval("(" + response + ")"));
}});
};

UI(自定义标签)

自定义有两种方式:uimethods(方法)和uimodule(模块)

创建玩一下uimethods,新创建一个py文件

#_*_coding:utf-8_*_

def abcd(self):
return '自定义uimethod方法'

uimethods

主文件

#_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web
#导入UImethod
import uimethods
#'ui_methods':uimethods 设置下即可
settings = {
'template_path':'template',
'static_path':'static',
'static_path_prefix':'/static/',
'ui_methods':uimethods
} class MainHandler(tornado.web.RequestHandler):
def get(self):
dic={'name':'abc'}
self.render('index.html',**dic)
app=tornado.web.Application([
(r"/index", MainHandler),
],**settings) if __name__ == "__main__":
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

html页面中加入自定方法即可

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>index.html</h1>
//自定义方法
{{abcd()}} </body>
</html>

演示效果

自定义uimedule(代码改动不多)

html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>index.html</h1>
<p>{{abcd()}}</p>
<p>自定义module</p>
//这里可以传递参数
{% module test_mod(123) %}
</body>
</html>

html

uimodules文件

#_*_coding:utf-8_*_
from tornado.web import UIModule class test_mod(UIModule):
#render是死的 最后返回的就是这个方法
def render(self, *args, **kwargs):
return 'uimodule.', args

uimodules

主文件

#_*_coding:utf-8_*_
import tornado.ioloop
import tornado.web
import uimethods
import uimodules settings = {
'template_path':'template',
'static_path':'static',
'static_path_prefix':'/static/',
'ui_methods':uimethods,
'ui_modules':uimodules,
} class MainHandler(tornado.web.RequestHandler):
def get(self):
dic={'name':'abc'}
self.render('index.html',**dic)
app=tornado.web.Application([
(r"/index", MainHandler),
],**settings) if __name__ == "__main__":
app.listen(8888)
tornado.ioloop.IOLoop.current().start()

运行效果:

自定义当方法在以后的应用是很广泛的,tornado 的方法不熟悉,完全可以用这个方法自己写

用户认证

简单说一下session和cookie 关系

      由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
简图:

上图可以看出cookie中不会存在敏感信息,重要的信息存储在服务器端的session中

Tornado是没有session 的,如下图这么处理的

这个方法不怎么安全,连接Tornado机制的就很容易伪造

实现tornado源生验证(很少会用这个方式来完成登陆验证)

主文件

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self):
#从cookie中获取key=login_user的值
login_user = self.get_secure_cookie("login_user", None)
if login_user:
#获取cookie成功就打印这个登陆名
self.write(login_user)
else:
self.redirect('/login') class LoginHandler(tornado.web.RequestHandler):
def get(self):
#self.current_user()
self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs):
#获取前端传递过来的 name和password
username = self.get_argument('username')
password = self.get_argument('password')
if username == 'lily0912' and password == '':
#登陆成功就设置cookie,key=login_user,值=lily0912
self.set_secure_cookie('login_user', 'lily0912')
#跳转到首页
self.redirect('/index')
else:
self.render('login.html', **{'status': 'name or password error!!!!'}) settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'asdassdasdsd123'
} application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="{{static_url("commons.css")}}" rel="stylesheet" />
</head>
<body>
<h1>登陆</h1>
<form action="/login" method="post">
<p>user:<input name="username" type="text"/></p>
<p>password:<input name="password" type="password" /> </p>
<input type="submit" value="submit" />
</form>
</body>
</html>

login

验证:

登陆成功后跳转页面,然后可以看到服务器给客户端的cookie信息。

自定义session验证

写cookie过程:

  • 将值进行base64加密
  • 对除值意外的内容进行签名,哈希算法(无法逆向解析)
  • 拼接 签名 + 加密值

读cookie过程:

  • 读取 签名 + 加密值
  • 对签名进行验证
  • base64解密,获取值内容

所以,我们会将base64加密的值返回给用户。而对于session,他只会将签名返回给用户,然后根据签名获取redis或数据库中保存的其他值。即:在session中,签名和session值的集合是一一对应的。

python魔法方法(为tornado 增加session功能就靠它了)

简单说下这个例子是python模仿字典工作

class Foo(object):
def __init__(self, key, value):
self.key = []
self.value = []
self.key.append(key)
self.value.append(value) def __len__(self):
return len(self.key) def __getitem__(self, item):
try:
__index = self.key.index(item)
return self.value[__index]
except ValueError:
raise KeyError('can not find the key') def __setitem__(self, key, value):
if key not in self.key:
self.key.append(key)
self.value.append(value)
else:
__index = self.key.index(key)
self.value[__index] = value def __delitem__(self, key):
try:
__index = self.key.index(key)
del self.key[__index]
del self.value[__index]
except ValueError:
raise KeyError('can not find the key') def __str__(self):
result_list = []
for index in xrange(len(self.key)):
__key = self.key[index]
__value = self.value[index]
result = __key, __value
result_list.append(result)
return str(result_list) def __iter__(self):
self.__index = 0
return self def next(self):
if self.__index == len(self.key):
self.__index = 0
raise StopIteration()
else:
__key = self.key[self.__index]
__value = self.value[self.__index]
result = __key, __value
self.__index += 1
return result def __reversed__(self):
__result = self.value[:]
__result.reverse()
return __result def __contains__(self, item):
if item in self.value:
return True
else:
return False a = Foo('scolia', 'good')
a[123] = 321
a[456] = 654
a[789] = 987
print a.key
print len(a)
del a[789]
print a
for x, y in a:
print x, y
print reversed(a)
print 123 in a
print 321 in av

演示代码

['scolia', 123, 456, 789]
4
[('scolia', 'good'), (123, 321), (456, 654)]
scolia good
123 321
456 654
[654, 321, 'good']
False
True

执行结果

这个东西没有弄过的的熟悉一下。确实有的魔法的感觉。

Tornado 实现session

显示熟悉一下流程

application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings)

根据url匹配都会找到对应的类比如:class LoginHandler(tornado.web.RequestHandler)

都会继承这个tornado.web.RequestHandler父类,首先父类会初始化RequestHandler.__init__() ,最后还调用self.initialize(**kwargs)了这个类。这个里面什么都没有。主要是留给我扩展用的

最后执行LoginHandler 类中的方法

我们有做的就是在执行LoginHandler方法之前  生成session 就OK了。

可以这么做:

自己写个基类继承tornado.web.RequestHandler 
class BaseHandler(tornado.web.RequestHandler):
#继承后直接改写这个方法就行
def initialize(self):
在这里写session内容就OK了
pass
下面的子类直接继承BaseHandler
class MainHandler(BaseHandler):
class LoginHandler(BaseHandler):

OK现在开始实现session

#!/usr/bin/env python
# -*- coding:utf-8 -*- import tornado.ioloop
import tornado.web
from hashlib import sha1
import os, time #生成session id
session_id=lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest() class Session(object):
def __init__(self,obj):
self.obj=obj
def __getitem__(self, key):
pass
def __setitem__(self, key, value):
#创建session_id
token=session_id()
#设置cookie的 key这个无所谓,起个名就行
cookie_key='_session'
self.obj.set_secure_cookie(cookie_key,token)
def __delitem__(self, key):
pass class BaseHandler(tornado.web.RequestHandler):
def initialize(self):
#将self传递给session方法,原因很简单Session方法本身无法将cookie写入LoginHandle对象中。因为它没有这个方法
self.mysesson=Session(self) class MainHandler(BaseHandler): def get(self):
#从cookie中获取key=login_user的值
login_user = self.get_secure_cookie("login_user", None)
if login_user:
#获取cookie成功就打印这个登陆名
self.write(login_user)
else:
self.redirect('/login') #RequestHandler.__init__()实例化方法
class LoginHandler(BaseHandler):
def get(self):
#self.current_user()
self.render('login.html', **{'status': ''}) def post(self, *args, **kwargs):
username = self.get_argument('username')
password = self.get_argument('password')
if username == 'lily0912' and password == '':
#self.set_secure_cookie('login_user', 'lily0912')
#成功登陆就设置状态True
self.mysesson['login_status']='True'
self.redirect('/index')
else:
self.render('login.html', **{'status': 'name or password error!!!!'}) settings = {
'template_path': 'template',
'static_path': 'static',
'static_url_prefix': '/static/',
'cookie_secret': 'asdassdasdsd123'
} application = tornado.web.Application([
(r"/index", MainHandler),
(r"/login", LoginHandler),
], **settings) if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()

看下session是否写入成功

Tornado(二)的更多相关文章

  1. web框架详解之tornado 二 cookie

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

  2. tornado 01 路由、输入与输出

    tornado 01 路由.输入与输出 一.安装tornado pyvip@Vip:~$ workon py3env #安装python3的虚拟环境 (py3env) pyvip@Vip:~$ pip ...

  3. tornado框架的简单实用

    一.安装模块 pip3 install tornado 二.简单的起服务的方法 import json, datetime from tornado.web import RequestHandler ...

  4. Python之Tornadoweb框架使用

    本文主要讲解Tornadoweb框架的安装和介绍及其简单使用. 一. 安装介绍 Tornado是一个Python Web框架和异步网络库,最初是在FriendFeed上开发的.通过使用非阻塞网络I / ...

  5. pip下载加速的方式

    两种方式 一.临时方式 可以在使用pip的时候加参数-i https://pypi.tuna.tsinghua.edu.cn/simple. 例如下载或者更新: 下载:pip install -i h ...

  6. Python框架之Tornado(二)请求阶段

    概述 上图是tornado程序启动以及接收到客户端请求后的整个过程,对于整个过程可以分为两大部分: 启动程序阶段,又称为待请求阶段(上图1.2所有系列和3.0) 接收并处理客户端请求阶段(上图3系列) ...

  7. 【tornado】系列项目(二)基于领域驱动模型的区域后台管理+前端easyui实现

    本项目是一个系列项目,最终的目的是开发出一个类似京东商城的网站.本文主要介绍后台管理中的区域管理,以及前端基于easyui插件的使用.本次增删改查因数据量少,因此采用模态对话框方式进行,关于数据量大采 ...

  8. tornado框架之路二

    二.路由系统 路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类. #!/usr/bin/env pyth ...

  9. python运维开发(二十二)---JSONP、瀑布流、组合搜索、多级评论、tornado框架简介

    内容目录: JSONP应用 瀑布流布局 组合搜索 多级评论 tornado框架简介 JSONP应用 由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. ...

随机推荐

  1. Linux下如何强制中断一个程序的执行?

    CTRL + C  中断 CTRL + Z  暂时放到后台 CTRL + D  保存退出

  2. Linux rpm yum 等安装软件

    任何程序都是先写代码,拿到源码去编译得到一个目标程序. 1  编译的过程复杂有需要准备编译的环境,和硬件有关,32位64位,内核的不同等等所以需要编译多次     Java特殊但是他需要安装jvm, ...

  3. SSO的几种跨域方案

    在此只是记录一下自己在尝试SSO跨域实现的过程中学到的几种跨域方案,不包含任何例子和具体的实现方法. 最近在尝试SSO的跨域,看了好多资料,然后自己记录了一下可以实现的方法: ①跳转所有站点设置coo ...

  4. JVM学习二:JVM之类加载器之加载分析

    前面一遍,我们对类的加载有了一个整体的认识,而这一节我们细节分析一下类加载器的第一步,即:加载. 一.概念 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区 ...

  5. 【BZOJ3745】Norma [分治]

    Norma Time Limit: 20 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description Input 第1行,一个整数N: ...

  6. Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)

    题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...

  7. NB二人组(一)----堆排序

    堆排序前传--树与二叉树简介 特殊且常用的树--二叉树  两种特殊的二叉树 二叉树的存储方式 二叉树小结 堆排序 堆这个玩意....... 堆排序过程: 构造堆: 堆排序的算法程序(程序需配合着下图理 ...

  8. L - SOS Gym - 101775L 博弈

    题目链接:https://cn.vjudge.net/contest/274151#problem/L 题目大意:给你一个1*n的方格,两个人轮流放字母,每一次可以放"S"或者&q ...

  9. php常用表单验证类用法实例

    <?php /** * 页面作用:常用表单验证类 * 作 者:欣然随风 * QQ:276624915 */ class class_post { //验证是否为指定长度的字母/数字组合 func ...

  10. python进阶之py文件内置属性

    前言 对于任何一个python文件来说,当python解释器运行一个py文件,会自动将一些内容加载到内置的属性中:一个模块我们可以看做是一个比类更大的对象. 查看模块的内置属性 我们先创建一个典型的p ...