天天看點

python 網站 模闆轉義

在python的字元串中,有的符号要想表達其本意,需要在前面加上

\

符号,例如單引号,如果要在字元串中表現它,必須寫成

\'單引号裡面\'

樣式,才能實作一對單引号以及裡面的内容,否則,它就表示字元串了。

在HTML代碼中,也有類似的問題,比如

>

等,就是代碼的一部分,如果直接寫,就不會顯示在網頁裡,要想顯示,同樣需要轉義。另外,如果在網頁中有表單,總會有别有用心的人向表單中寫點包含

>

等字元的東西,目的就是要攻擊你的網站,為了防治邪惡之輩,也需要将使用者輸入的字元進行轉義,轉化為字元實體,讓它不具有HTML代碼的含義。

轉義字元串(Escape Sequence)也稱字元實體(Character Entity)。在HTML中,定義轉義字元串的原因有兩個:第一個原因是像“<”和“>”這類符号已經用來表示HTML标簽,是以就不能直接當作文本中的符号來使用。為了在HTML文檔中使用這些符号,就需要定義它的轉義字元串。當解釋程式遇到這類字元串時就把它解釋為真實的字元。在輸入轉義字元串時,要嚴格遵守字母大小寫的規則。第二個原因是,有些字元在ASCII字元集中沒有定義,是以需要使用轉義字元串來表示。

模闆自動轉義

Tornado 2 開始的模闆具有自動轉義的功能,這讓開發者省卻了不少事情。看一個例子。就利用上一講中建立的開發架構。要在首頁模闆中增加一個表單送出功能。

修改template/index.html檔案,内容如下:

<DOCTYPE html>
<html>
    <head>
        <title>Loop in template</title>
        <link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
    </head>
    <body>
    <h1>aaaAAA</h1>
    <p>There is a list, it is <b>{{info}}</b></p>
    <p>I will print the elements of this list in order.</p>
    {% for element in info %}
        <p>{{element}}</p>
    {% end %}
    <br>
    {% for index,element in enumerate(info) %}
        <p>info[{{index}}] is {{element}}
        {% if element == "python" %}
            <p> <b>I love this language--{{element}}</b></p>
        {% end %}
    {% end %}

    {% if "[email protected]" in info %}
        <p><b>A Ha, this the python lesson of hiekay, It is good! His email is {{info[2]}}</b></p>
    {% end %}
    <h2>Next, I set "python-tornado"(a string) to a variable(var)</h2>
    {% set var="python-tornado" %}
    <p>Would you like {{var}}?</p>
    <!--增加表單-->
    <form method="post" action="/option">
        <p>WebSite:<input id="website" name="website" type="text"></p>
        <p><input type="submit" value="ok,submit"></p>
    </form>
    </body>
</html>
           

在增加的表單中,要将内容以

post

方法送出到

"/option"

,是以,要在url.py中設定路徑,并且要建立相應的類。

然後就在handler目錄中建立一個新的檔案,命名為optform.py,其内容就是一個類,用來接收index.html中

post

過來的表單内容。

#!/usr/bin/env python
#coding:utf-8

import tornado.web

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

class OptionForm(tornado.web.RequestHandler):   
    def post(self):
        website = self.get_argument("website")      #接收名稱為'website'的表單内容
        self.render("info.html",web=website)
           

為了達到接收表單post到上述類中内容的目的,還需要對url.py進行如下改寫:

#!/usr/bin/env python
#coding:utf-8

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

from handler.index import IndexHandler
from handler.optform import OptionForm
url=[
    (r'/', IndexHandler),
    (r'/option', OptionForm),

    ]
           

還要注意,我在建立立的optform.py中,當接收到來自表單内容之後,就用另外一個模闆

info.html

顯示所接收到的内容。這個檔案放在template目錄中,代碼是:

<DOCTYPE html>
<html>
    <head>
        <title>Loop in template</title>
        <link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
    </head>
    <body>
    <h1>My Website is:</h1>
    <p>{{web}}</p>
    </body>
</html>
           

這樣我們就完成表單内容的送出和顯示過程。

從上面的流程中,是否體驗到這個架構的優勢了?不用重複敲代碼,隻需要在架構内的不同地方增加内容,即可完成網站。

示範運作效果:

我在表單中輸入了

<script>alert('bad script')</script>

,這是多麼陰險毒辣呀。

然而我們的tornado是不懼怕這種攻擊的,因為它的模闆自動轉義了。當點選按鈕送出内容的時候,就将那些陰險的符号實體化,成為轉義之後的符号了。于是就這樣了:

輸入什麼,就顯示什麼,不會因為輸入的内容含有陰險毒辣的符号而網站無法正常工作。這就是轉義的功勞。

不轉義的辦法

在tornado中,模闆實作了自動轉義,省卻了開發者很多事,但是,事情往往沒有十全十美的,這裡省事了,一定要在别的地方費事。例如在上面那個info.html檔案中,我打算在裡面加入我的電子信箱,但是要像下面代碼這樣,設定一個變量,主要是為了以後修改友善和在其它地方也可以随意使用。

<DOCTYPE html>
<html>
    ...(省略)
    <body>
    <h1>My Website is:</h1>
    <p>{{web}}</p>
    {% set email="<a href='mailto:[email protected]'>Connect to me</a>"%}
    <p>{{email}}</p>
    </body>
</html>
           

本來希望在頁面中出現的是

Connect to me

,點選它之後,就直接連接配接到發送電子郵件。結果,由于轉義,出現的是下面的顯示結果:

實作電子郵件超連結未遂。

這時候,就需要不讓模闆轉義。tornado提供的方法是:

  • 在Application函數執行個體化的時候,設定參數:autoescape=None。這種方法不推薦使用,因為這樣就讓全站模闆都不轉義了,願意嘗試,不妨進行修改試一試,我這裡就不展示了。
  • 在每個頁面中設定{% autoescape None %},表示這個頁面不轉義。也不推薦。
  • 以上都不推薦,我推薦的是:{% raw email %},想讓哪裡不轉義,就在那裡用這種方式,比如要在email超級連結那裡不轉移,就寫成這樣好了。于是修改上面的代碼,看結果為:
<DOCTYPE html>
<html>
    <head>
        <title>Loop in template</title>
        <link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
    </head>
    <body>
    <h1>My Website is:</h1>
    <p>{{web}}</p>
     {%raw email="<a href='mailto:[email protected]'>Connect to me</a>"%}
    </body>
</html>           

如此,實作了不轉義。

以上都實作了模闆的轉義和不轉義。

url轉義

有些符号在URL中是不能直接傳遞的,如果要在URL中傳遞這些特殊符号,那麼就要使用它們的編碼了。編碼的格式為:%加字元的ASCII碼,即一個百分号%,後面跟對應字元的ASCII(16進制)碼值。例如 空格的編碼值是"%20"。

在python中,如果用utf-8寫了一段位址,如何轉義成url能夠接收的字元呢?

在python中有一個urllib子產品:

>>> import urllib

>>> #假設下面的url,是utf-8編碼
>>> url_mail='http://www.hiekay.com/[email protected]'

>>> #轉義為url能夠接受的
>>> urllib.quote(url_mail)
'http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com'

#反過來,一個url也能轉移為utf-8編碼格式,請用urllib.unquote()

>>>urllib.unquote('http%3A//www.hiekay.com/email%3F%3Dhiekay%40gmail.com')
'http://www.hiekay.com/[email protected]'           

下面抄錄幫助文檔中的内容,供用到的朋友參考:

quote(s, safe='/')
    quote('abc def') -> 'abc%20def'

    Each part of a URL, e.g. the path info, the query, etc., has a
    different set of reserved characters that must be quoted.

    RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists
    the following reserved characters.

    reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                  "$" | ","

    Each of these characters is reserved in some component of a URL,
    but not necessarily in all of them.

    By default, the quote function is intended for quoting the path
    section of a URL.  Thus, it will not encode '/'.  This character
    is reserved, but in typical usage the quote function is being
    called on a path where the existing slash characters are used as
    reserved characters.

unquote(s)
    unquote('abc%20def') -> 'abc def'.

quote_plus(s, safe='')
    Quote the query fragment of a URL; replacing ' ' with '+'

unquote_plus(s)
    unquote('%7e/abc+def') -> '~/abc def'
           

轉義是網站開發中要特别注意的地方,不小心或者忘記了,就會糾結。