Tornado-06, Tornado template escaping and template inheritance

Time:2022-11-23

Tornado template escaping and template inheritance


1. Escaping of templates

By default, Tornado will automatically escape the content in the template, converting tags into corresponding HTML entities. This prevents websites with database backends from being attacked by malicious scripts. For example, say you have a comments section on your website where users can add whatever they want to discuss. While some HTML tags do not pose a significant threat when markup and style conflicts (such as no closing tags in comments), tags can allow attackers to load other JavaScript files, opening the door to cross-site scripting attacks, XSS or vulnerabilities.

First, we create a new lesson5 folder under the tornado folder and add the templates folder
Create a new start1.py file under lesson5 and add the following code

#The route is:
(r'/temp',TempHandler),

class TempHandler(tornado.web.RequestHandler):
    def get(self):
        username = self.get_argument('name','no')
        import time
        urllist = [
            ('https://www.baidu.com/','Baidu'),
            ('https://www.zhihu.com/', 'Zhihu'),
        ]  
        self.render('escape.html',
                    username=username,
                    time=time,
                    urllist=urllist,
                    )

Create a new escape.html file under the templates folder and add the following code to the body of the file

{% for url in urllist %}
    <a href="{{ url[0] }}" target="_blank" >{{ url[1] }}</a> <br>
{% end %}

We have added a link here, and we can click on the corresponding page on the page to jump to other pages.


Tornado-06, Tornado template escaping and template inheritance


Next, we add or modify the following code in the TempHandler service:

atag = " <a href='https://www.baidu.com/' target='_blank'>'---Baidu---'</a><br> "
self.render('escape.html',
            username=username,
            time=time,
            urllist=urllist,
            atag=atag
            )

And add the following code in the body of escape.html

{{ atag }}

Now let’s take a look at the page


Tornado-06, Tornado template escaping and template inheritance

We found that the code we added at this time was output as a string and was not parsed by the browser. This is escaping, and tornado will automatically escape, and all the output will be used as a string. This is done It can prevent some malicious code from being executed when it is output to the front end, resulting in data leakage.

Of course, this is automatically escaped by default. If you don’t want to escape, it is also possible. There are the following methods:

1. Cancel global escaping and add configuration items in Application

autoescape=None,

Tornado-06, Tornado template escaping and template inheritance

2. Comment out the autoescape=None above and add it at the beginning of the html document

{% autoescape None %} #Realize the unescaping of the entire document

Tornado-06, Tornado template escaping and template inheritance

#When the global and document are not escaped, you can use escape() to enable the escape of variables
{{ atag }}
{{ escape(atag) }}

3. You can also use {% raw xxx %} to output unescaped content

{% raw atag %}

Tornado automatically enables escaping by default. You can choose whether to escaping according to your needs, but you must know that the original intention of escaping is to prevent the browser from accidentally executing malicious code, so you need to choose carefully when removing escaping.

static_url function to generate the URL in the static directory

<script src="{{ static_url(js/jquey-2.2.0.min.js) }}"></script>
<script src="/static/js/jquey-2.2.0.min.js"></script>

There are two ways to refer to static files. Use the above form, so why use static_url instead of hardcoding it in your template? There are several reasons. First, the static_url function creates a hash value based on the file content and adds it to the end of the URL (parameter v of the query string). This hash value ensures that the browser always loads the latest version of a file rather than the previously cached version. It is very useful whether it is in the development stage of your application or when it is deployed to the production environment, because your users no longer have to clear the browser cache in order to see your static content.

2. Template inheritance

Extract the same content of multiple pages and put it in a base.html file. The different content of each sub-html file uses a block statement to occupy the place, and the sub-html file rewrites the content in this block.

The base.html file is as follows:

 <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Tornado</title>
    </head>
    <body>
        {% block body%}
        <br>
            this is base
        {% end %}
        {% block js %}{% end %}
    </body>
    </html>

extend.html is as follows

<! -- Inherited parent template -->
{% extends "./base.html" %}

The server code is as follows:

#Route mapping is as follows
(r'/base',BaseIndexHandler),
(r'/extends',ExtendsHandler),

class BaseIndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render('base.html')

class ExtendsHandler(tornado.web.RequestHandler):
    def get(self):
        username = 'haha'
        self.render('extend.html')

Tornado-06, Tornado template escaping and template inheritance
Tornado-06, Tornado template escaping and template inheritance


In the above, we can see that nothing is written in the inherited template, but the parent template is inherited, and all the contents of the parent template can be inherited, saving a lot of repetitive code.

# Inherit from parent module
{% extend filename %}

#When inheriting, the child template replaces the block with the same name in the parent template
{% block name %}
    #The content written here will replace the content in the template, if you do not write the content of the parent template
{% end %}

#Import other template files
{% include filename %}

First add the following code in the body of base.html

  {% block handy%}
        <br>
            this is handy
  {% end %}

After inheritance, you can override the block of the parent class
Create a new extend.html file under the templates folder

{% extends "./base.html" %}
 <! -- Inherit the title block -->
    {% block title %} {{ username }} {% end %}

    <! -- Inherits the body block -->
    {% block body %}
        {% if username!='no' %}
            User {{ username }} is welcome to log in
            <br>
                I inherited hahaha
            <br>
            hahahaha{% include "./include.html" %}
        {% else %}
            You are not logged in
        {% end %}
    {% end %}

Remember, when a page inherits other pages, it needs to implement the corresponding block to be effective, and the code outside the block has no effect.

Of course, templates can be introduced, include.html is as follows:

You are not logged in

Add the following in extends.html:

hahahaha{% include "./include.html" %}

You can see the effect after execution.


Tornado-06, Tornado template escaping and template inheritance