在这个例子中,我们将只通过存储在安全cookie里的用户名标识一个人。当某人首次在某个浏览器(或cookie过期后)访问我们的页面时,我们展示一个登录表单页面。表单作为到LoginHandler路由的POST请求被提交。post方法的主体调用set_secure_cookie()来存储username请求参数中提交的值。

代码如下:

class BaseHandler(tornado.web.RequestHandler):

def get_current_user(self):

return self.get_secure_cookie("username")

class LoginHandler(BaseHandler):

def get(self, *args, **kwargs):

self.render('login.html')

def post(self, *args, **kwargs):

self.set_secure_cookie("username",self.get_argument("username"))

class WelcomeHandler(BaseHandler):

@tornado.web.authenticated

def get(self, *args, **kwargs):

self.render('index.html',user=self.current_user)

class LogoutHandler(BaseHandler):

def get(self, *args, **kwargs):

if (self.get_argument("logout",None)):

self.clear_cookie("username")

self.redirect('/')

def server_function():

cookie='bZJc2sWbQLKos6GkHn/VB9oXwQt8S0R0kRvJ5/xJ89E='

tornado.options.parse_command_line()

app = tornado.web.Application(handlers=[(r"/", WelcomeHandler),(r"/login",LoginHandler),(r"/logout",LogoutHandler)],template_path=os.path.join(os.path.dirname(__file__),"template"),

static_path=os.path.join(os.path.dirname(__file__),"static"),ui_modules={'Book':HelloModule},cookie_secret=cookie,xsrf_cookies=True,login_url="/login")

http_server = tornado.httpserver.HTTPServer(app)

http_server.listen(options.port,address='127.0.0.1')

tornado.ioloop.IOLoop.instance().start()

首先来看下代码的运行原理:

第一步:首先来看WelcomeHandler。这个类的get函数被@tornado.web.authenticated装饰器给装饰,我们进入这个装饰器的代码看下具体的实现:

def authenticated(method):

@functools.wraps(method)

def wrapper(self, *args, **kwargs):

if not self.current_user:

if self.request.method in ("GET", "HEAD"):

url = self.get_login_url()

if "?" not in url:

if urlparse.urlsplit(url).scheme:

# if login url is absolute, make next absolute too

next_url = self.request.full_url()

else:

next_url = self.request.uri

url += "?" + urlencode(dict(next=next_url))

self.redirect(url)

return

raise HTTPError(403)

return method(self, *args, **kwargs)

return wrapper

第二步:authenticated首先判断self.current_user是否存在,self.crrent_user的值在tornado.web.RequestHandler中获得。这是一个RequestHandler的类属性。返回的是_current_user,而且_current_user 是通过self.get_current_user()获取的

@property

def current_user(self):

if not hasattr(self, "_current_user"):

self._current_user = self.get_current_user()

return self._current_user

而我们在BaseHandler中重写了get_current_user,从客户端发送的cookie中获取username的值。那么如果是第一次访问或者是cookie值失效后,得到的current_user将会是空

def get_current_user(self):

return self.get_secure_cookie("username")

第三步:如果current_user为空,网页将重定向到login_url设置的页面连接。url = self.get_login_url()。在这个函数中通过return self.application.settings["login_url"]

返回重定向的url

def get_login_url(self):

self.require_setting("login_url", "@tornado.web.authenticated")

return self.application.settings["login_url"]

第四步:进入登录界面的处理函数LoginHandler。在登录界面中将进行username的cookie值设置

class LoginHandler(BaseHandler):

def get(self, *args, **kwargs):

self.render('login.html')

def post(self, *args, **kwargs):

self.set_secure_cookie("username",self.get_argument("username"))

第五步:再次登录,由于current_user已经存在,因此跳转到index.html网页,并显示登录的用户名

class WelcomeHandler(BaseHandler):

@tornado.web.authenticated

def get(self, *args, **kwargs):

self.render('index.html',user=self.current_user

代码已经解释完了,我们来看下具体的网页访问例子:

第一步:浏览器中输入http://127.0.0.1:8003/,将会自动跳转到http://127.0.0.1:8003/login?next=%2F

后台打印:

[I 180105 10:11:05 web:2063] 302 GET / (127.0.0.1) 0.33ms

[I 180105 10:11:05 web:2063] 200 GET /login?next=%2F (127.0.0.1) 0.68ms

浏览器中查看cookie值,此时只有设置的_xsrf值

第二步:此时在网页中输入用户名并点击login。再次查看cookie值,已经存在了username的cookie值

第三步 再次登录http://127.0.0.1:8003/。可以看到没有跳转到登录界面,而是直接显示了登录用户。

整个后台的打印:

[I 180105 10:11:05 web:2063] 302 GET / (127.0.0.1) 0.33ms

[I 180105 10:11:05 web:2063] 200 GET /login?next=%2F (127.0.0.1) 0.68ms

[I 180105 10:14:50 web:2063] 200 POST /login (127.0.0.1) 1.46ms

[I 180105 10:16:17 web:2063] 200 GET / (127.0.0.1) 0.64ms

最新文章

  1. [笔记]linux磁盘管理
  2. [AR]高通Vuforia Getting Started
  3. 做参数可以读取参数 保存参数 用xml文件的方式
  4. 正确的选择log级别
  5. 在ubunt14.04(linux)下利用cmake编译运行opencv程序
  6. Delphi中如何将 Exe 程序或其他资料打包在内,使用时再释放使用(转)
  7. linux系统的 suid/guid简单介绍 linux suid guid
  8. 搭建Eclipse、Resin Web开发环境
  9. 前端学习书籍大全 包含PDF地址
  10. HNOI2016 网络
  11. directx11编程中遇到的错误及解决方法
  12. Define Constraints That Are Minimal and Sufficient 设定不多不少的约束
  13. ID3决策树预测的java实现
  14. js 判断是否为空对象、空数组
  15. 基于ZKWeb + Angular 4.0的开源管理后台Demo
  16. Python之测试webservice接口
  17. What is “Neural Network”
  18. Mvc 批量图片上传
  19. 配置Sublime Text2的python运行环境(Sublime Text 3也类似)
  20. 20165310 学习基础和C语言基础调查

热门文章

  1. unix网络编程第四章----基于TCP套接字编程
  2. FZU 2224 An exciting GCD problem(GCD种类预处理+树状数组维护)同hdu5869
  3. awk在企业中最常用的语句
  4. CodeForces - 600F Edge coloring of bipartite graph
  5. Uoj #350. 新年的XOR
  6. oracle function dtrace
  7. iOS上如何让按钮(UIbutton)文本左对齐展示
  8. 计算机的一些经典书籍CS经典书单
  9. 借助autoit操作上传下载对话框(参数化)
  10. cocos2dx3.0 对象池