tornado 之authenticated和session 简单登陆

1.登陆检查(装饰器的使用)html

咱们登陆的时候须要验证,可是若是有不少地方须要验证,这个时候就会出现不少重复代码的状况,这个时候咱们须要一个不改变函数运行,又能给函数加上验证过程方法,很明显,咱们能够使用装饰器来达到这个功能,代码以下:web

def auth(fun):
    def wrapper(self,*args,**kwargs):
        id = self.get_secure_cookie('ID')
        if id:
            return fun(self,*args,**kwargs)
        else:
            self.redirect('/login')
    return wrapper

#定义好装饰器以后,就能够直接去修饰须要验证的方法  redis

class IndexHandler(BaseHandler):
    @auth
    def get(self):
        self.write('登陆成功---index')

使用装饰器能够很方便咱们去作登陆检查,能够节省出大量的代码,增长程序的可读性和程序总体的美观。数据库

2.authenticated浏览器

虽然咱们本身能够作这个登陆检查,可是在tornado内部给咱们提供了一个内置的装饰器`authenticated`这个能够帮咱们自动的进行登陆验证,`authenticated`能够省去咱们本身重复造轮子的过程,可是在使用的时候须要注意几点:安全

# Application中添加配置
login_url='/login',

# 重写 get_current_user 方法
class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        current_user = self.get_secure_cookie('ID')
        if current_user:
            return current_user
        return None
# 装饰须要验证的方法      
@authenticated     

有些时候咱们须要跳转到以前的页面怎么作呢?当咱们使用`authenticated`的时候咱们能够十分方便的作这件事情。咱们观察跳转以后的url就能够发现,若是是使用`authenticated`装饰器装饰以后,而跳转到登陆页面以后,在登陆页面的url中,能够看到最后面会添加上一个next参数,这个就是咱们刚才跳转的路由,经过这个参数,咱们就能够很方便的跳转回以前的的路由,具体实现以下:服务器

class LoginHandler(BaseHandler):
    def get(self):
        nextname = self.get_argument('next','')
        self.render('authenticated.html',nextname=nextname)
    def post(self):
        nextname = self.get_argument('next', '')
        username = self.get_argument('name','')
        username = User.by_name(username)
        passwd = self.get_argument('password', '')
        print(username)
        if username and username[0].password == passwd:
            self.set_secure_cookie('ID',username[0].username,max_age=100)
            self.redirect(nextname)
        else:
            self.render('authenticated.html',nextname=nextname)

页面代码作以下的改变就行:cookie

<form method="post" action="/login?next={{nextname}}">
    <p>用户名<br><input type="text" name="name"></p>
    <p>密码<br><input type="text" name="password"></p>
    <input type="submit">
</form>

配合使用模板的传参,能够很方便的进行跳转。session

3.sessionapp

cookie中不能存放存放用户的敏感信息,那么cookie里面就只能存放一些随机的字符串,可是若是这样的话,那么服务器端又怎样知道是那个用户呢?

咱们能够创建一个会话来作这件事情,这个会话里面会存储随机字符串和能够惟一肯定用户的信息。

因为tornado没有内置session模块,因此使用pycket这个模块中封装好的session模块来,要想使用首先要安装:

pip install pyckey
pip install redis

安装好以后就能够使用了,使用很简单,注意一下几点:

from pycket.session import SessionMixin

# 1.在Application添加 pycket 的配置
pycket={
  'engine': 'redis',
  'storage': {
    'host': 'localhost',
    'port': 6379,
    'db_sessions': 5,
    'db_notifications': 11,
    'max_connections': 2**31,
  },
  'cookies': {
    'expires_days': 30,
    'max_age': 100
  },
},

# 2.改 self.set_secure_cookie 为 self.session.set
# self.set_secure_cookie('ID',username[0].username,max_age=100)
self.session.set('user',username[0].username)

# 3.改 self.get_secure_cookie 为 self.session.get
# current_user = self.get_secure_cookie('ID')
current_user = self.session.get('user')

以上就能够使用`session`了,这个`session`的工做原理是以下:

1. 使用`set`方法,为输入的用户信息生成一串随机字符串
2. 将这个字符串和对应的用户信息作成键值对,放到`redis`数据库中
3. 将字符串处理以后放入到`cookie`中,发送给浏览器
4. 浏览器请求时将`cookie`中的信息发送到服务器,`tornado`接受到以后解析出来,去`redis`查找,找到就验证成功

使用`session`有以下好处:

1. 能够不要在`cookie`中存放敏感信息
2. 减小数据传输须要的时间
3. 减小加密解密的时间

`session`的使用很简单,可是安全性会有一个很大的提高,所以使用很是多,必定要掌握使用方法。

4.跨站防伪造请求的防范

跨站伪造请求(Cross-site request forgery)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), 简称为 `XSRF`,是个性化 Web 应用中常见的一个安全问题。前面的连接也详细讲述了` XSRF `攻击的实现方式。

当前防范` XSRF` 的一种通用的方法,是对每个用户都记录一个没法预知的` cookie `数据,而后要求全部提交的请求中都必须带有这个` cookie `数据。若是此数据不匹配 ,那么这个请求就多是被伪造的。

`Tornado `有内建的 `XSRF `的防范机制,要使用此机制,只须要在模板中添加以下代码:

<form method="post" action="/login?next={{nextname}}">
    {% module xsrf_form_html() %}   <!--添加这行代码就能够了-->
    <p>用户名<br><input type="text" name="name"></p>
    <p>密码<br><input type="text" name="password"></p>
    <input type="submit">
相关文章
相关标签/搜索