zoukankan      html  css  js  c++  java
  • cookie、session登录验证csrf

    cookie

    在上节课,我们简单了解了登录过程,但是很明显,每次都需要登录,但是在平常逛网站的只需要登录一次,那么网站是如何记录登录信息的呢?

    有没有什么办法可以让浏览器记住登录信息,下次再次打开的时候,可以自动登录呢?

    设置cookie与获取cookie

    import sys
    import time
    import tornado.web
    import tornado.ioloop
    import tornado.httpserver
    import tornado.options
    from tornado.web import RequestHandler
    from tornado.options import define,options
    import util.ui_modules
    import util.ui_methods
    # import time
    from data.connect import session
    from data.user_modules import UserDetails, User
    
    define('port',default=8080,help='run server',type=int)
    class MainHandler(RequestHandler):
        def get(self):
            self.write('cookie')
            self.set_cookie('cookie_test','aqweqwas')
            self.set_cookie('cookie_test2','aqweqwas2',expires=time.time()+60)  #设置过期时间
            self.set_cookie('cookie_test3','aqweqwas3',expires_days=1)  #设置过期天数
            self.set_cookie('cookie_test4','aqweqwas4',path='/')  #设置cookie路径
            self.set_cookie('cookie_test5','aqweqwas5',httponly=True)  #设置后js代码获取不到此cookie值
            self.set_cookie('cookie_test6','aqweqwas6',max_age=120,expires=time.time()+60)  #设置过期时间max_age的优先级大于expires
            self.set_secure_cookie('cookie_test7','aqweqwas7',max_age=120,expires=time.time()+60)  #设置加密cookies
    
    class GetHandler(RequestHandler):
        def get(self):
            self.write('get_cookie')
            self.write('<br>')
            cookie_name = self.get_cookie('cookie_test4')
            cookie_name2 = self.get_secure_cookie('cookie_test7')
    
            self.write(cookie_name)
            self.write('<br>')
            self.write(cookie_name2)
    application = tornado.web.Application(
        handlers=[
            (r'/',MainHandler),
            (r'/get',GetHandler),
        ],
        debug=True,
        template_path = 'templates',
        static_path='static',
        # autoescape = None, #全局取消转义
        ui_methods=util.ui_methods,
        ui_modules=util.ui_modules,
        cookie_secret ='qwe123', #cookie加盐
    )
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.current().start()

    登录验证:

    第一步:导入装饰器

    from tornado.web import authenticated

    第二步:声明 BaseHandler

    class BaseHandler(RequestHandler):
        def get_current_user(self):
            current_user = self.get_secure_cookie('user_ID')
            if current_user:
                return current_user
            return None

    第三步:配置登录路由

        login_url = '/login'

    第四步:装饰需要验证的请求

    class BuyHandler(BaseHandler):
        @authenticated
        def get(self):
            self.write('嗨,小可爱!')

    在完成登录之后,再来看看,我们从一个路由跳转到登录页面之后,再完成登录之后,该如何跳转到之前的页面呢?

    第一步:获取之前路由

    class LoginHandler(BaseHandler):
        def get(self):
            next_name = self.get_argument('next','')
            self.render('in_out.html',nextname=next_name)

    在使用 authenticated 之后,如果验证不成功,会自动跳转到登录路由,并且在 URL 后面加上 next 参数,next 参数的参数值就是之前的路由

    第二步:修改模板文件

        <form method="post" action="/login?next={{ nextname }}">

    在模板中添加 next 参数,并且参数值为之前的路由

    第三步:修改post方法

        def post(self):
            '''验证逻辑'''
            user = self.get_argument('name',None)
            password = self.get_argument('password',None)
            next_name = self.get_argument('next','')
            print(next_name)
            # username = session.query(User).filter(User.username == user).first()
            username = User.get_name(user)
            print(username)
            if username and  password == username.password:
                #如果判断用户可以登录,我们设置这样一个加密的cookie进去
                self.set_secure_cookie('user_ID',user)
                self.redirect(next_name)
            else:
                self.write('登录失败')

    获取之前的页面的路由

    当登录验证通过之后,设置加密的 cookie ,并跳转到之前的路由

    完整的python代码与模板html代码如下:

    import sys
    
    import time
    import tornado.web
    import tornado.ioloop
    import tornado.httpserver
    import tornado.options
    from tornado.web import RequestHandler,authenticated
    from tornado.options import define,options
    import util.ui_modules
    import util.ui_methods
    # import time
    from data.connect import session
    from data.user_modules import UserDetails, User
    
    define('port',default=8080,help='run server',type=int)
    
    class BaseHandler(RequestHandler):
        def get_current_user(self):
            current_user = self.get_secure_cookie('user_ID')
            if current_user:
                return current_user
            return None
    
    class BuyHandler(BaseHandler):
        @authenticated
        def get(self):
            self.write('嗨,小可爱!')
            #第一,如果有参数next,肯定是没登录的时候
            #没登录,会跳转到/login,app里面设置的
            #在login里面,form表单没提交之前,get里面获取一下这个值
            #在获取出来之后,吧这个值传到post请求里面
            #post获取这个值,此值就是一个url
            #直接跳转到此url
    
    
    class LoginHandler(BaseHandler):
        def get(self):
            next_name = self.get_argument('next','')
            self.render('in_out.html',nextname=next_name)
    
        def post(self):
            '''验证逻辑'''
            user = self.get_argument('name',None)
            password = self.get_argument('password',None)
            next_name = self.get_argument('next','')
            print(next_name)
            # username = session.query(User).filter(User.username == user).first()
            username = User.get_name(user)
            print(username)
            if username and  password == username.password:
                #如果判断用户可以登录,我们设置这样一个加密的cookie进去
                self.set_secure_cookie('user_ID',user)
                self.redirect(next_name)
            else:
                self.write('登录失败')
    
    
    application = tornado.web.Application(
        handlers=[
            (r'/buy',BuyHandler),
            (r'/login',LoginHandler),
    
        ],
        debug=True,
        template_path = 'templates',
        static_path='static',
        # autoescape = None, #全局取消转义
        ui_methods=util.ui_methods,
        ui_modules=util.ui_modules,
        cookie_secret ='qwe123', #cookie加盐
        login_url = '/login'
    )
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.current().start()

    in_out.html代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>tornado</title>
    </head>
    <body>
        <form method="post" action="/login?next={{ nextname }}">
            <p>用户名<input type="text" name="name"></p>
            <p>密码<input type="password" name="password"></p>
            <input type="submit">
        </form>
    </body>
    </html>

     session

    通过刚才的学习,可以用了解到 cookie 中的信息可以用来保存用户的登录信息,但是coolkie 是很容易被拦截的,所有其中必定不能有用户的任何私密信息,那么又有什么办法可以让服务器保存用户的登录信息,但是cookie中又不会有用户的任何信息呢?

    第一步:安装模块

    pip install pycket  #tornado中用于连接redis的模块
    pip install redis

    第二步:导入模块

    from pycket.session import SessionMixin

    第三步:继承SessionMixin

    class BaseHandler(tornado.web.RequestHandler, SessionMixin):

    第四步:在application 中添加配置

    配置 redis 的相关信息

    配置 cookie 的过期时间

        pycket = {
            'engine':'redis',
            'storage':{
                'host':'localhost',
                'port':6379,
                'db_sessions':5,
                'max_connections':2**10,
            },
            'cookies':{
                'expires_days':7
            }
        }

    第五步:改设置cookie为设置session

    self.session.set('user_ID',user)

    第六步:改获取cookie为获取session

    current_user = self.session.get('user_ID')

    完整代码如下:

    import sys
    
    import time
    import tornado.web
    import tornado.ioloop
    import tornado.httpserver
    import tornado.options
    from tornado.web import RequestHandler,authenticated
    from tornado.options import define,options
    from pycket.session import SessionMixin
    import util.ui_modules
    import util.ui_methods
    # import time
    from data.connect import session
    from data.user_modules import UserDetails, User
    
    define('port',default=8080,help='run server',type=int)
    
    class BaseHandler(RequestHandler,SessionMixin):
        def get_current_user(self):
            current_user = self.session.get('user_ID')
            if current_user:
                return current_user
            return None
    
    class BuyHandler(BaseHandler):
        @authenticated
        def get(self):
            self.write('嗨,小可爱!')
            #第一,如果有参数next,肯定是没登录的时候
            #没登录,会跳转到/login,app里面设置的
            #在login里面,form表单没提交之前,get里面获取一下这个值
            #在获取出来之后,吧这个值传到post请求里面
            #post获取这个值,此值就是一个url
            #直接跳转到此url
    
    
    class LoginHandler(BaseHandler):
        def get(self):
            next_name = self.get_argument('next','')
            self.render('in_out.html',nextname=next_name)
    
        def post(self):
            '''验证逻辑'''
            user = self.get_argument('name',None)
            password = self.get_argument('password',None)
            next_name = self.get_argument('next','')
            print(next_name)
            # username = session.query(User).filter(User.username == user).first()
            username = User.get_name(user)
            print(username)
            if username and  password == username.password:
                #如果判断用户可以登录,我们设置这样一个加密的cookie进去
                # self.set_secure_cookie('user_ID',user)
                self.session.set('user_ID',user)
                self.redirect(next_name)
            else:
                self.write('登录失败')
    
    
    application = tornado.web.Application(
        handlers=[
            (r'/buy',BuyHandler),
            (r'/login',LoginHandler),
    
        ],
        debug=True,
        template_path = 'templates',
        static_path='static',
        # autoescape = None, #全局取消转义
        ui_methods=util.ui_methods,
        ui_modules=util.ui_modules,
        cookie_secret ='qwe123', #cookie加盐
        login_url = '/login',
        pycket = {
            'engine':'redis',
            'storage':{
                'host':'localhost',
                'port':6379,
                'db_sessions':5,
                'max_connections':2**10,
            },
            'cookies':{
                'expires_days':7
            }
        }
    )
    if __name__ == '__main__':
        tornado.options.parse_command_line()
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.current().start()

    XSRF:防止跨域请求伪造

    使用session可以保证用户信息不被cookie泄漏,那如果如果攻击者不想获取用户信息,只是在提交 form 表单时攻击,该怎么防范呢?

    模板添加

    {% module xsrf_form_html() %}

    代码如下:

    <body>
        {% module xsrf_form_html() %}
        <form method="post" action="/login?next={{ nextname }}">
            <p>用户名<input type="text" name="name"></p>
            <p>密码<input type="password" name="password"></p>
            <input type="submit">
        </form>
    </body>

    Tornado 有内建的 XSRF 的防范机制,要使用此机制,只需要在模板中添加如上代码

    页面效果显示:

    生成一段关于xsrf的随机字符串,防止伪造

  • 相关阅读:
    ReentrantLock与Condition构造有界缓存队列与数据栈
    ReentrantLock
    文件下载
    scala初学
    bootstrap table 显示连续序号,分页有效
    web中servletcontext和applicationContext
    checkbox是否选中判断
    bookstrap form表单简单-smart-form
    charts柱状图,定时刷新
    js对象和json的区别
  • 原文地址:https://www.cnblogs.com/taoge188/p/10660614.html
Copyright © 2011-2022 走看看