1.模板的轉義
Tornado 默認會自動轉義模板中的內容,把標簽轉換為相應的HTML實體。這樣可以防止后端為數據庫的網站被惡意腳本攻擊。比如,
你的網站中有一個評論部分,用戶可以在這里添加任何他們想說的文字進行討論。雖然一些HTML標簽在標記和樣式沖突時不構成重大威脅
(如評論中沒有閉標簽),但標簽會允許攻擊者加載其他的JavaScript文件,打開通向跨站腳本攻擊、XSS或漏洞之門。
首先看下面的例子
(r'/temp',TempHandler), class TempHandler(tornado.web.RequestHandler): def get(self): username = self.get_argument('name','no') import time urllist = [ ('https://www.kaiyuanzhognguo.com/','開源中國'), ('https://www.baidu.com/','百度'), ('https://www.zhihu.com/','知乎'), ] self.render('escape.html', username=username, time=time, urllist=urllist, )
HTML文件如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% if username!='no' %} 歡迎用戶 {{ username }} 登錄 <br> <img src="/static/images/c.jpg" width="250" height="250" > <br> {% else %} 您還沒有登錄 {% end %} <br> {% for url in urllist %} <a href="{{ url[0] }}" target="_blank" >{{ url[1] }}</a> <br> {% end %} </body> </html>
這個地方在之前的基礎上有添加了一點內容,可以在頁面上引用我們的靜態文件,這里我們引入了一個圖片。
這個地方我們添加了鏈接,我們可以在頁面上點擊相應的頁面來跳轉到其他的頁面去。
接下來我們在服務其中添加如下代碼:
atag = "<a href='https://www.baidu.com/' target='_blank'>'---百度---' </a><br> " self.render('03escape.html', username=username, time=time, urllist=urllist, atag=atag )
這個時候我們再來看看頁面,我們發現這個時候我們加上的這個代碼是作為一個字符串輸出,並沒有被瀏覽器解析出來,這個就是轉義,tornado會自動的轉義,把所有的輸出都作為字符串,這樣做的就能防止一些惡意代碼在輸出到前端時被執行,從而造成數據泄露。
當然這個默認自動是轉義的,如果不要轉義也是可以的,有如下方法:
#1.全局轉義,在Application中添加配置項
autoescape=None,
#2.在文檔最開始添加
{% autoescape None %} #實現整個文檔轉義
#在開啟全局和文檔不轉義的情況下,可以使用 escape() 來開啟變量的轉義
{{ atag }}
{{ escape(atag) }}
#3.也可以使用 {% raw xxx %} 來輸出不轉義內容
{% raw atag %}
tornado是默認自動開啟轉義的,大家可以根據需求來選是否轉義,但是要知道轉義的本意是來防止瀏覽器意外執行惡意代碼的,所以去掉轉義的時候需要謹慎選擇。
static_url函數來生成static目錄下的URL
<!--html--> <script src="{{ static_url(js/jquey-2.2.0.min.js) }}"></script> <script src="/static/js/jquey-2.2.0.min.js"></script>
引用靜態文件有上面 兩種寫法,使用上面的這種形式,那么為什么使用static_url而不是在你的模板中硬編碼呢?有如下幾個原因。其一,static_url函數創建了一個基於文件內容的hash值,並將其添加到URL末尾(查詢字符串的參數v)。這個hash值確保瀏覽器總是加載一個文件的最新版而不是之前的緩存版本。無論是在你應用的開發階段,還是在部署到生產環境使用時,都非常有用,因為你的用戶不必再為了看到你的靜態內容而清除瀏覽器緩存了。
2.模板的繼承
把多個頁面相同的內容提取出來放在一個base.html文件中,各個子html文件不同的內容 使用塊語句占位,子html文件重寫這個塊中的內容。
base.html文件如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}Tornado{%end%}</title> <link rel="shortcut icon" href="{{ static_url('images/favicon.ico') }}" type="image/x-icon" /> </head> <body> {% block body%} this is base {% end %} {% block js %}{% end %} </body> </html>
extend.html如下
<!--繼承的父模板--> {% extends "base.html" %}
tornado 后台代碼如下:
#路由映射如下 (r'/base',BaseIndexHandler), (r'/extends',ExtendsHandler), class BaseIndexHandler(tornado.web.RequestHandler): def get(self): self.render('04base.html') class ExtendsHandler(tornado.web.RequestHandler): def get(self): username = self.get_argument('name','no') self.render('05extends.html')
在上面,我們可以看到繼承的模板里面沒有寫任何東西,只是繼承了父模板,同樣父模板的所有內容就都可以繼承過來了,省去了大量的重復部分代碼。
#從父模塊繼承 {% extends filename %} #繼承時子模板替換父模板中同名的塊 {% block name %} #這里寫的內容會替換模板中的內容,如果不寫使用父模板的內容 {% end %}
#引入其他的模板文件
{% include filename %}
繼承之后可以重寫父類的塊
<!--繼承title塊--> {% block title %} {{ username }} {% end %} <!--繼承body塊--> {% block body %} {% if username!='no' %} 歡迎用戶 {{ username }} 登錄 <br> <img src="/static/images/c.jpg" width="250" height="250" > <br> {% else %} 您還沒有登錄 {% end %} {% end %}
記住,當頁面繼承其他頁面之后,需要實現相應的塊才有作用,在塊外面的代碼是沒有作用的。
當然可以引入模板,include.html如下:
在extends.html中添加如下:
hahahaha{% include "./include.html" %}
之后就可以看執行的效果
HTML文件
<!DOCTYPE html> {% autoescape None %}<!--全局不轉義--> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> welcome {{username}} 登錄 <br> {% if username != 'no' %} 歡迎用戶{{username}} 登錄 <br> {% else %} 您還沒有登錄 <br> {% end %} <br> {% for url in urllist %} <a href="{{url[0]}}" target="_blank">{{url[1]}}</a> <br> {% end %} {{atga}} <br> {% raw atga %} <br> <!--局部不轉義--> {{ escape(atga) }} <!--局部轉義--> <script src="{{static_url('js/jquery-2.2.0.min.js')}}"></script> <script src="/static/js/jquery-2.2.0.min.js"></script> </body> </html>