Tornado提升之数据库应用安全

数据库

  • 概述:tornado没有自带的ORM , 对于数据库需要自己去适配
    • 目前python3.6+tornado还没有比较完善的驱动
  • 链接:
    • 在应用启动时创建一个数据库链接实例,提供各个RequestHandler使用。

    • 在RequestHandler中通过self.application来获取其应用

        # application.py:创建数据库实例
        self.db = SunckSql(config.mysql["host"],config.mysql["user"],config.mysql["passwd"],
                           config.mysql["dbName"])
         -------------------------------------
        # index.py
        from sunckSql import SunckSql
        class studentsHandler(RequestHandler):
            def get(self):
                # 去数据据中提取数据
                stus = self.application.db.get_all_obj("select * from tb_student","tb_student")
                self.render("student.html",stus=stus)     
      

应用安全

  • Cookie

    • 普通cookie(不安全)

      • 设置

          原型:self.set_cookie(name,value,domain=None,expires=None,path="/",expires_day=None,**kwags)
          参数:name:cookie名,
               value:cookie值
               domain:提交cookie时匹配的域名
               path:提交COOKIE时匹配的路径
               expirse:cookie的有效期,可以是时间戳、整数、时间元组、datatime类型,为UTC时间
               expirse_days:cookie的有效期,天数,优先级低于expires
          ----------------------------------------------------------
        

      -原理:设置cookie实际上是通过设置header的Set-Cookie来实现的

            两中方法都可以设置cookie
            self.set_header("Set-Cookie","luciano=nice;Path=/")
            推荐:self.set_cookie("luciano","computerGOD") 
      
      • 获取

          原型:self.get_cookie(name,default=None)
          参数:
              name: 要获取的 cookie名称
              default:如果名为name 的cookie不存在,则返回default值
        
      • 清除

        • 作用:删除名为name ,并同时匹配domain 和 path的 cookie’

            原型:self.clear_cookie(name,path="/",domain=None)
                self.clear_all_cookies(path="/",domain=None)
          
        • 注意:执行清除cookie操作后并不是立即删除浏览器端的Cookie而是给cookie的值设置为空,
          并改变其有限期限为失效。真正删除cookie是由浏览器自己去清理

    • 安全cookie (加密)

      • django没有的Cookie

      • cookie是存在客户端浏览器的数据,很容易被篡改

      • tornado提供了一种对cookie进行简易的加密方式来防止cookie被而已篡改

      • 设置:

        • 需要为应用配置一个用来给cookie进行混肴的加密密钥

            import base64
            import uuid
            base64.b64encode(uuid.uuid4().bytes+uuid.uuid4().bytes)
            >>> 会生成一串字符串(100亿年不会出现重复)
            ---------------------------------------
            将生成好的密钥配置到config.py
            "cookie_secret":"tfA8keUBRy2y+HdXA91DSSDVq3v3EUp6gbsGqeHUHTA=",
          
        • 原型:

            self.set_secure_cookie(name=,value=,expires_days=30,version=None,**kwargs)
          
        • 作用:设置一个带有签名和时间戳的cookie,可以防止伪造

            客户端获取到的cookie值:2|1:0|10:1593503769|5:quezi|8:V0ROTUQ=|f218bbb14c9c39bacf3ce303cbe48d61f112c04d3140a5b68d793dffcda9e3fe
            说明:安全cookie的版本,默认是2版本,":"前面是位数,":"后面是相应位数对应的值,
                 "0":           默认
                 “1593503769”:时间戳
                 “quezi”:    cookieName
                 "V0ROTUQ=":  base64的编码的cookie值
                 “f218bbb14c9c39bacf3ce303cbe48d61f112c04d3140a5b68d793dffcda9e3fe”:签名值,不带长度说明
          
      • 获取

        • 原型:

             self.get_secure_cookie(name=,value=,max_age_days=31,min_version=None)      
             参数:
                value:       如果cookie存在且验证通过,返回cookie值,否则返回None         
                max_age_days:max_age_days(过滤安全cookie的时间戳) 不同于 expires(设置浏览器总cookie的有效时间) ,
          
      • 注意:也不是完全的安全,一定程度上增加了破解cookie的难度
        以后不要用cookie存储一些敏感性数据

  • XSRF

    • 跨站请求伪造
      当用户从浏览器上粘贴几个标签放到一个普通的html页面上去登录我们服务器的"cookie计数器"地址时,
      在我们不知情,我们未授权的情况下,“cookie计数器”网站cookie被使用,以至于cookie计数器网址
      认为是它自己网站调用了Handler逻辑

        黑客:html  file:///C:/Users/Shinelon/Desktop/test.html
         <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
        </head>
        <body>
        <img src="http://127.0.0.1:8080/cookienum">
        <h1>去看看吧 ,我可能把你弄坏</h1>
        </body>
        </html>
        ------------------------------------------
        服务器:index.py
        class cookienum(RequestHandler):
            def prepare(self):
                # 往往通过预处理函数来做cookie计数,
                pass
        
            def get(self,*args,**kwargs):
                # 获取cookie中 name 为 count的值,判断count的数量
                # 如果没获取到那说明是第一次,即count=1 否则就是第“>1次”,则让count += 1 。
                # 最后更新cookie中count值
                count = self.get_cookie("count",None)
                if not count:
                    count = 1
                else:
                    count = int(count)
                    count += 1
                self.set_cookie("count",str(count))
        
                self.render("cookinum.html",count=count)
         ----------------------------------------------
         这样下来 只要黑客不断刷新他的html 网页,我们服务器就会不断的更新cookie 
         name为count的值
      
    • 上一个程序使用的时GET方式模拟攻击,为了防止这种攻击,一般对于相对安全的操作是不会放在GET请求中的,
      一般会用做POST请求

    • XSRF保护:(同源策略)

        同源:同协议  、 同域名  、 同端口
      
    • 开启XSRF保护

        config.py添加
        "xsrf_cookies":True
      
    • 应用:

      • 模板 {% module xsrf_form_html() %}

          在form表单上面加上:
              {% module xsrf_form_html() %}
          作用:
               1.为浏览器设置了_xsrf的安全cookie,这个cookie会在关闭浏览器失效
                  cookie:Set-Cookie: _xsrf=2|0a7a73bc|93954775aead64d33a14231bf4aeb0dd|1593510433; Path=/
               2.为模板表单添加了一个隐藏域,名为_xsrf,值为_xsrf这个cookie的值
                  隐藏域:<input type="hidden" name="_xsrf" value="2|0a7a73bc|93954775aead64d33a14231bf4aeb0dd|1593510433">
          -----------------------------------------------------------------
        
      • 注意:这这方式看似解决了跨站请求伪造,但是实际上依然未解决:

          -----------------------------------------------------------
          黑客: html  file:///C:/Users/Shinelon/Desktop/test.html
          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Title</title>
          </head>
          <body>
          # 将服务器上的代码隐藏于 copy到黑客本地的html中
          <input type="hidden" name="_xsrf" value="2|0a7a73bc|93954775aead64d33a14231bf4aeb0dd|1593510433">
          <img src="http://127.0.0.1:8080/cookienum">
          <h1>去看看吧 ,我可能把你弄坏</h1>
          </body>
          </html>
          --------------------------------------------------------------
          服务器 index.py
          class postfile(RequestHandler):
          def get(self):
              self.render("postfile.html")
          def post(self,*args,**kwargs):
              count = self.get_cookie("count", None)
              if not count:
                  count = 1
              else:
                  count = int(count)
                  count += 1
              self.set_cookie("count", str(count))
              self.redirect("/cookienum")
          -------------------------------------------------------
           没有安全
        
      • 非模板(三种方式)

        • 手动设置 _xsrf的cookie

          • {% module xsrf_form_html() %} 这句话的内部原理:

              手动创建<input>隐藏域 ,并设置name属性值为_xsrf,value属性值名为_xsrf的cookie值
              --------------------------------------------
              # 手动设置_xsrf 的 cookie
              class setxsrfcookie(RequestHandler):
                  def get(self,*args,**kwargs):
                      #设置一个_xsrf的cookie
                      self.xsrf_token
                      self.finish("ok")
              -----------------------------------------
              html:
              <input id="hi" type="hidden" name="_xsrf" value="">
              <script type="text/javascript">
              function getCookie(name) {
                  var cook = document.cookie.match("\\b"+name+"=([^;]*)\\b")  //match() 查找  "\\b"二进制
                  return cook ? cook[1] : undefined  // 三目运算符 ?
              }
              document.getElementById("hi").value = getCookie("_xsrf")
              console.log(getCookie("_xsrf"))
            
        • 发起ajax请求

                <button onclick="login()">登录</button>
                ---------------------------------
                 // ajax POST:
                function login(){
                    console.log("_xsrf")
                    // _xsrf = 值&username=值&passwd = 值
                    $.post("/postfilenew","_xsrf="+getCookie('_xsrf')+"&username="+"luciano"+"&passwd="+"1234",function (data) {
                            console.log(data)
                            alert("ok")
                    })
                }
                ------------------------------
                // ajax原生:(推荐使用)
                function login(){
                    data = {
                        "username":"lucinao",
                        "passwd":"123",
                    }
                    // 将 data 对象转成 JSON字符串
                    dataStr = JSON.stringify(data)
                    $.ajax({
                        url : "/postfilenew",
                        method:"POST",
                        data : dataStr,
                        success:function () {
                                alert("ok")
                        },
                        // 设置请求头
                        headers:{
                            "X-XSRFToken":getCookie("_xsrf"),
                        }
                    })
                }
          
        • 问题:需要手动添加_xsrf的cookie,需要再进入主页时候自动设置上_xsrf的cookie

            路由最下面加上:
            (r'/(.*)$',index.StaticFileHandler,
            {"path":os.path.join(config.BASE_DIRS,"static/html"),"default_filename":"index.html"})
            ------------------------
            index.py加上:
            class StaticFileHandler(tornado.web.StaticFileHandler):
                # 重写父类__init__方法
                def __init__(self,*args,**kwargs):
                    super(StaticFileHandler,self).__init__(*args,**kwargs)
                    # 在父类中手动设置_xsrf 的 cookie
                    self.xsrf_token
          
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值