Tornado-Lesson09-cookie登录验证-session和XSRF

一、cookie

  1.cookie的概念

    指服务器为了识别用户身份,缓存在浏览器本地的数据;多用于保存登录状态

  2.cookie的使用

    1)设置cookie

      set_cookie(name, value)

      set_cookie(name, value, expires = time.time()+n)  设置过期时间为n秒

      set_cookie(name, value, expires_days = n)  设置有效期,n天

      set_cookie(name, value, max_age = n, expires = time.time()+n)  max_age;min_age限制有效期最大和最小时间

      set_cookie(name, value, path = '/’)  设置路径

      set_cookie(name, value, httponly = True)  设置httponly = True,该cookie无法被js获取

      self.set_secure_cookie(name, value)  设置一个加密的cookie,需要在application中设置cookie_secret

      self.clear_cookie(name)  删除cookie,调用可以看到cookis信息为空

      self.clear_all_cookies()   删除此请求发送的全部cookie

      注:set_cookie中value不能包含空格,否则报错

    2)获取cookie

      self.get_cookie(name)

      self.get_secure_cookie(value) 

      注:get_secure_cookie获取的cookie是bytes类型,get_cookie获取的是str类型


二、登录验证

  1.利用cookie登录验证

    1)导入装饰器

      from tornado.web import authenticated

    2)声明BaseHandler

      class BaseHandler(tornado.web.RequestHandler):

        def get_current_user(self):

          current_user = self.get_secure_cookie('cookie_name')

          if current_user:

            return current_user

          return None

    3)配置路由

      在applaction中添加 login_url = '/login'

    4)调用装饰器验证请求

      继承BaseHandler,并使用装饰器@authenticated

      class BuyHandler(BaseHandler):

        @authenticated

        def get(self):

          self.write('BuyHandler')

     这样,当路由跳转BuyHandler时候,先判断有没有cookie,如果有,则正常显示页面。如果没有cookie信息,则跳转到login_url所配置的路由

 

  2.从某一路由跳转到登录页面的完整cookis验证流程

    cookie_test.py

 

import tornado.ioloop
import tornado.web
import tornado.httpserver
import tornado.options
import json
import time
import util.ui_methods
import util.ui_modules

from tornado.options import define, options

from data.user_module import User

from tornado.web import authenticated

import data

print(dir(data))
print(data.name)

define('port', default=8080, help='run port', type=int)
define('version', default='0.01', help='version', type=str)


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


class SetCookieHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.set_cookie('cookie_test', 'this_is_cookie_test')
        self.set_cookie('cookie_test_1', 'this_is_cookie_test_1', expires_days=1)  #设置有效期,生成时间+n秒
        self.set_cookie('cookie_test_2', 'this_is_cookie_test_2', expires_days=1)   #设置有效期1天
        self.set_cookie('cookie_test_3', 'this_is_cookie_test_3', expires_days=1, path='/test/')  # 设置有路径
        self.set_cookie('cookie_test_4', 'this_is_cookie_test_4', expires_days=1, httponly=True)  # js不可获取
        self.set_cookie('cookie_test_5', 'this_is_cookie_test_5', max_age= 120, expires=time.time() + 180) #限制最大时间
        self.set_cookie('cookie_test_6', 'this_is_cookie_test_6', max_age=120, expires=time.time() + 60)  # 限制最大时间
        self.set_secure_cookie('cookie_test_7', 'this_is_cookie_test_7')
        # self.clear_cookie('cookie_test')
        # self.clear_all_cookies()


class GetCookieHandler(tornado.web.RequestHandler):
    def get(self):
        get_cookie1 = self.get_cookie('cookie_test_1')
        get_cookie2 = self.get_cookie('cookie_test_2')
        get_cookie3 = self.get_secure_cookie('cookie_test_7')
        print(type(get_cookie1))
        print(type(get_cookie2))
        print(type(get_cookie3))
        self.write(get_cookie1 + '<br>' + get_cookie2 + '<br>' + str(get_cookie3, encoding = "utf-8"))


class LoginHandler(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        nextname = self.get_argument('next', '')
        self.render('login.html', nextname=nextname, error = None)


    def post(self, *args, **kwargs):
        nextname = self.get_argument('next', '')
        user = self.get_argument('name', '')
        username = User.by_name(user)
        password = self.get_argument('password', '')
        if username and password==username.password:
            self.set_secure_cookie('ID', username.username)
            # self.render('login_success.html',
            #             username = username.username
            #             )
            self.redirect(nextname)
        else:
            self.render('login.html', nextname=nextname, error = '用户名和密码错误')

class BuyHandler(BaseHandler):
    @authenticated
    def get(self, *args, **kwargs):
        self.write('这个问题冲钱就能解决')

application = tornado.web.Application(
    handlers=[
    (r"/login", LoginHandler),
    (r"/buy", BuyHandler),
    (r"/set", SetCookieHandler),
    (r"/get", GetCookieHandler)
    ],
    debug=True,
    static_path = 'static',
    template_path = 'templates',
    ui_methods=util.ui_methods,
    # ui_modules=util.ui_modules,
    cookie_secret = 'abcdefg',
    login_url = '/login',
    ui_modules={'UiModule':util.ui_modules.UiModule}
)

if __name__ == '__main__':
    tornado.options.parse_command_line()
    print(options.port)
    print(options.version)
    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

 

  login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Tornado</title>
</head>
<body>
{% if error %}
    用户名或密码错误
{% else %}
    Welcome!
{% end %}
<form method="post" action="/login?next={{ nextname }}">
    <p>用户名<br><input type="text" name="name"></p>
    <p>密码<br><input type="password" name="password"></p>
    <input type="submit">
</form>


</body>
</html>

    看上面代码,当输入网址,跳转到/buy路由时,BuyHandler继承了BaseHandler并使用了装饰器@authenticated,由以下该源码装饰器可以看出,该装饰器作用是判断是否有cookie;

    如果有,则正常返回get请求。

    如果没有则返回applaction中login_url配置的路由,并在后面加上"?next=next_url",next_url就是之前跳转过来的路由"/buy".

def authenticated(method):
    """Decorate methods with this to require that the user be logged in.

    If the user is not logged in, they will be redirected to the configured
    `login url <RequestHandler.get_login_url>`.

    If you configure a login url with a query parameter, Tornado will
    assume you know what you're doing and use it as-is.  If not, it
    will add a `next` parameter so the login page knows where to send
    you once you're logged in.
    """
    @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

    当没有cookie时候的运行结果:

                  

    当有cookie,正常跳转到写入数据

 

三、登录验证

四、XSRF

 

 

 

 

 

posted @ 2018-03-22 01:27  17-王晶龙-58  阅读(203)  评论(0编辑  收藏  举报