在这个例子中,我们将只通过存储在安全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

tornado安全应用之用户认证的更多相关文章

  1. Tornado web.authenticated 用户认证浅析

    在Web服务中会有用户登录后的一系列操作, 如果一个客户端的http请求要求是用户登录后才能做得操作, 那么 Web服务器接收请求时需要判断该请求里带的数据是否有用户认证的信息. 使用Tornado框 ...

  2. Nodejs之MEAN栈开发(八)---- 用户认证与会话管理详解

    用户认证与会话管理基本上是每个网站必备的一个功能.在Asp.net下做的比较多,大体的思路都是先根据用户提供的用户名和密码到数据库找到用户信息,然后校验,校验成功之后记住用户的姓名和相关信息,这个信息 ...

  3. Django--自定义用户认证

    Django自带的用户认证 以前都是用Django自带的用户认证,用户名字段一对一关系对应Django--User表(其实它也是继承了abstractbaseuser). 1 2 3 from dja ...

  4. linux(十二)___Apache服务器用户认证、虚拟主机的配置

    创建xiangkejin  zhangsan两个用户 可看见文件中创建的两个用户: 建立虚拟目录并配置用户认证 ①建立虚拟目录 /xiangkejin ②在Apache的主配置文件httpd.conf ...

  5. [django]用户认证中只允许登陆用户访问(网页安全问题)

    当设计一个重要网页时,一般要求未从登陆界面访问的用户不能进入其他页面,那么需要如何设置呢? 如下 django中的url.py urlpatterns = [    url(r'^$', 'login ...

  6. 使用JDBC实现Oracle用户认证

    两天时间写的小品,以前的J2EE环境基本使用框架.现在使用JDBC配合Oracle存储过程模拟了一下用户注册和用户认证. 一.添加必须的jar包 需要JDBC连接Oracle的包和shiro-core ...

  7. ldap实现用户认证

    LDAP的用户认证类. public class LDAPHelper { private DirectoryEntry _objDirectoryEntry; /// <summary> ...

  8. auth用户认证库

    关于auth库,建议如下:1. ion_auth,基于Redux重写而成,非常不错的认证库,国外用的很多,几个最新的ci2.0.2基础上的开源系统(如doveforum)都用它,支持ci 2.0和以上 ...

  9. 禅道PMS兼容redmine用户认证接口

    项目地址:https://github.com/web3d/zentao-redmine-userauth zentao-redmine-userauth 做了一个基本的用户认证接口,兼容redmin ...

随机推荐

  1. Select函数实现

    int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, ...

  2. 小程序-生成一个小程序码画在canvas画布上生成一张图片分享出去

    这个需求我遇到过2次.一次是在识别二维码后跳转到其它页面,另一次是识别二维码后进入到生成小程序码的当前页面. 我有一个梦想,就是成为一名黑客!!!!!! 小程序中js wx.request({     ...

  3. HDU 5890 Eighty seven(DP+bitset优化)

    题目链接 Eighty seven 背包(用bitset预处理)然后对于每个询问O(1)回答即可. 预处理的时候背包. #include <bits/stdc++.h> using nam ...

  4. POJ 1860 Currency Exchange 最短路+负环

    原题链接:http://poj.org/problem?id=1860 Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Tota ...

  5. Java-HashMap原理解析

    本文分析HashMap的实现原理. 数据结构(散列表) HashMap是一个散列表(也叫哈希表),用来存储键值对(key-value)映射.散列表是一种数组和链表的结合体,结构图如下: 简单来说散列表 ...

  6. Android 学习之路和App开发框架

    学习之路: 1. http://www.stormzhang.com/android/2014/07/07/learn-android-from-rookie/ 框架: 2. https://gith ...

  7. android ListView详解(转)

    在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示.抽空把对ListView的使用做了整理,并写了个小例子,如下图. 列表的显示需要三 ...

  8. 【jQuery】input textarea 文本变化的动态监听

    实时监听Input textarea文本变化的监听事件:[但不包含通过js动态添加改变的文本事件] HTML: <textarea style="display: none" ...

  9. 【css】设置div位于浏览器的最底层,离用户最远

    有时候切换发现某块div一直悬浮在最上层,怎么设置div位于浏览器的最底层.离用户最远? <style> .in{ z-index: -1; } </style> 然后引用in ...

  10. xamarin android 获取根证书代码

    Java.Security.KeyStore keyStore = Java.Security.KeyStore.GetInstance("AndroidCAStore"); ke ...