在这个例子中,我们将只通过存储在安全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. mysql开发必知必会

    mysql的数据库的数据库,即存储mysql数据库的底层目录,是在/var/lib/mysql目录下(Linux,win在目录下的data中). 我们新创建的数据库db1就是在/var/lib/mys ...

  2. Python入门--19--else语句、with语句

    1.else与while连用: x=input('请输出一个整数:') while x>0 x=x-2 print(x) else: print('x已经小于等于零了!') 2.else与try ...

  3. serializeObject 的应用

    function sendForm() { var invOrderModelWrapper = {}; // 头 var objHeader = $('#invOrderForm').seriali ...

  4. TopCoder SRM596 DIV2 1000: SparseFactorialDiv2

    题意: For an integer n, let F(n) = (n - 0^2) * (n - 1^2) * (n - 2^2) * (n - 3^2) * ... * (n - k^2), wh ...

  5. 海量端口扫描工具masscan

    海量端口扫描工具masscan   masscan号称是互联网上最快的端口扫描工具,可以6分钟扫描整个互联网,每秒可以发送一百万个数据包.为了提高处理速度,masscan定制了TCP/IP栈,从而不影 ...

  6. 一些yuv视频下载地址

    因为测试需要下载一些yuv视频地址,现存一个可以下载yuv视频的地址以备后用 http://trace.eas.asu.edu/yuv/index.html ftp://ftp.ldv.e-techn ...

  7. luogu P2158 [SDOI2008]仪仗队

    题目描述 作为体育委员,C君负责这次运动会仪仗队的训练.仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图 ...

  8. MySQL中数据类型(char(n)、varchar(n)、nchar(n)、nvarchar(n)的区别)(转)

    一.第一种 char(n)和varchar(n)的区别: 在这里我们可以清楚的看到他们表面的区别就是前面是否有var,在这里解释一下var是什么意思,var代表“可变的”的意思 下面看个例子: )// ...

  9. 跳转到指定页面popToViewController用法

    有人问popToViewController的用法 就写了下了 希望能帮到有需要的人 [self.navigationController popToViewController:[self.navi ...

  10. chm 转 pdf 工具推荐与对比

    在进行推荐chm转pdf的软件之前,首先来了解一下为什么我们要将chm转为pdf. CHM是英语“Compiled Help Manual”的简写,即“已编译的帮助文件”.CHM是微软新一代的帮助文件 ...