Home  >  Article  >  Operation and Maintenance  >  How to deploy Django

How to deploy Django

WBOY
WBOYforward
2023-05-20 17:26:191991browse

PART 1. Security first

The best time to fix vulnerabilities is during development.

1.1 CSRF TOKEN

In Django’s security framework, CSRF TOKEN is a crucial security strategy. However, in many cases, some students who have just come into contact with Django will find that the form they finally wrote will report an error during POST. After some searches, they find that it is a CSRF TOKEN problem, and then follow the online method to divide the form by three, five, and two. All CSRF TOKEN configurations in settings.py were removed and the code ran normally. Little do you know that this kind of operation will greatly affect the security of the website and increase the cost of patching vulnerabilities in the later stage. Eliminating security issues during the development stage is the lowest cost.

Because the official documentation has explained the relevant content of CSRF TOKEN in detail, the specific usage will not be described here. Here we recommend a more convenient usage, which is less sensitive to developers during development and does not require special care about whether the Token has been sent successfully.

Add {% csrf_token %} to the total parent template page, and make the following settings in the <script> section: </script>

How to deploy Django

This way All non-GET|HEAD|OPTIONS|TRACE requests initiated through AJAX in JQuery will automatically include CSRF TOKEN (part of the code to obtain CSRF TOKEN is not listed). If you are using other HTTP libraries or Fetch, make the corresponding settings. Can.

1.2 API security design

In some cases, our Web service will also provide some API services to the outside world for calls by other systems. For these API interfaces, CSRF must be turned off. Otherwise it won't work properly at all. We should also take other security measures to prevent API interfaces from being abused. In addition to the normal passing parameters, we should ensure that these parameters are not tampered with by middlemen, and only allow people with authority to call the corresponding interface. For this reason, we need to introduce several additional passing parameters: timestamp, sign, access_key, access_token.

This pair of parameters includes access_key and access_token. access_key is equivalent to identifying the caller, and access_token is equivalent to the caller's secret key. The content of access_token should not be easily predicted, and access_key can choose a simpler string for the convenience of memory. Only when the two parameters match, the API call is considered legal.

Select the precision of the timestamp according to business requirements, you can choose seconds or milliseconds. The main purpose of adding a timestamp is to prevent this call from being replayed. The server should verify whether the timestamp passed by the client is within a time range. Timestamps that expire should be considered illegal requests. In order to ensure the authenticity of the parameters, another parameter sign needs to be introduced, because even if the timestamp is replayed, there is still a risk of tampering.

sign is the signature value of all parameters, which is generated by all parameter values ​​participating in hash calculation. Every time the parameters change, the sign needs to be regenerated to ensure the authenticity of the parameters. A commonly used algorithm is: sort the parameter value according to the alphabetical order of the parameter key, and use specific separators to connect all parameters, then perform hash calculation, and pass the sign parameter to the server together. For example, the existing parameter ak=2222&at=1111&timestamp=3333&key1=aaa, after sorting according to alphabetical order, is 22221111aaa3333, after adding the separator (|), it is 2222(|)1111(|)aaa(|)3333, and then This string calculates sha1 and generates a sign value. It is relatively simple to write in Python code:

How to deploy Django

1.3 Some miscellaneous items

In addition to the two more important points above, there are also There are some areas that require a little extra attention.

Turn off DEBUG mode in the production environment;

Do not add settings.py to version management, and protect SECRET_KEY;

Set ALLOWED_HOSTS;

Use the ORM provided by Django as much as possible to avoid directly executing SQL statements through .raw() and other methods. If it cannot be avoided, you must Escape parameters correctly to avoid SQL injection vulnerabilities;

Disable Django Admin as much as possible. If you must use it, please modify the default Admin URL;

PART 2. How to deploy

Pull the code from git, use pip to install project dependencies, and run the service through manage.py. This all looks good, but you really plan to use it in a production environment Do this?

2.1 Isolation environment

Under normal circumstances, there will only be one Python environment on our server. When deploying, we usually use pip to install the dependencies required for the project. These packages will Is installed into the global site-packages directory.

When deploying multiple projects, this method of installing dependencies can easily lead to dependency conflicts. To give a simple example, we now have two projects, Project-A and Project-B. Both A and B depend on different versions of the third-party package third-A. When we install -r requirements-a.txt through pip, The dependency third-A is installed into the global Python environment. When we install pip install -r requirements-b.txt again, third-A will also be installed again. At this time, if the versions that the two projects depend on are inconsistent, for example Project A requires version 1.0, and project B requires version 2.0, which will cause dependency conflicts and cause dependency installation to fail.

So how to solve this problem? What we can easily think of is that if we have multiple independent isolation environments and each project is deployed in an independent environment, then this problem will be easily solved. Virtualenv was born to solve this problem. It can create a separate running environment for each project to avoid dependency conflicts.

2.2 Version Management

We knew earlier how to create an isolated environment and deploy different projects in different environments, but there is a problem. The Python version used by all environments is the same. If you happen to need to deploy multiple different versions of Python projects, such as Python 2.7 (I know this version will not be maintained soon, but I will give an example here), Python 3.6 and Jython projects, installing them one by one seems a bit complicated. , even when compiling and installing, a certain compilation parameter is accidentally missing and needs to be recompiled, which increases the deployment workload to some extent.

We can use pyenv to manage the problems of multiple Python versions, and further use the pyenv plug-in pyenv-virtualenv to manage the problems of multiple Python versions and multiple virtual environments.

2.3 Gateway interface

After we have solved the problems of various environments, it is time to consider how to run the project. If you want to use python manage.py runserver 0.0.0.0 :80, that’s a bit too simple.

Django has built-in a simple WSGI implementation for us to start the Web service through the above method. If you just want to debug or only provide services to a few people, it is also an option. solution, although this solution does not look so elegant.

If you really want to deploy the application to an actual production environment, then you also need a high-performance WSGI Server, not the simple WSGI Server provided by django. Gunicorn and uWSGI are both relatively mainstream WSGI servers. Just choose one of them according to the actual deployment environment.

However, I personally prefer Gunicorn. Although uWSGI has the upper hand in many performance tests, the reason for choosing Gunicorn is that it is very simple compared to uWSGI and does not have very complicated and rarely used functions. , and some functions in uWSGI have been gradually supported by Nginx, and Gunicorn is relatively simple and convenient to configure. Another thing to note is that if you want to deploy on Windows, you may need to use Apache mod_wsgi.

2.4 Reverse proxy

After our WSGI Server is started, we need to consider the issue of reverse proxy. The reason why there is another layer of Nginx to perform reverse proxy is The following reasons:

Nginx is needed to handle static resources. If you set Django's DEBUG mode to False, you will find that many static resources such as CSS and JS cannot be loaded. This is because Django will not actively handle these requests, and Nginx needs to help handle them;

Use Nginx to perform load balancing of multiple backends. If your service is deployed on multiple servers, or a primary and backup deployment, these can be achieved by simple settings on Nginx;

directly There are certain security risks when uWSGI or Gunicorn are exposed. It will be more convenient to use Nginx to handle HTTP problems; That sentence, if your service is very simple and only accessed by a few people, there is no need to make such complicated settings.

2.5 Process Daemon

As of now, we have successfully deployed the service and can start providing services normally. But we think less about it. If our Django unfortunately exits for some unknown reason, then our Web service will become a 502. In order to ensure the stability of the service, we need to guard the Django process. When an unknown problem occurs and causes an abnormal exit, the required process needs to be automatically pulled up.

Using supervisor as a monitoring tool can ensure the stable survival of the Django process. It is important to be careful to avoid the Supervisord remote command execution vulnerability to avoid more serious accidents.

PART 3. Background service

Generally speaking, if you want to start a background service, celery is a universal choice, but many times we don’t want to introduce such heavy dependencies, so we need to Think of a way to start the background service.

A simple method is to make the command of manage.py, start our background service through ./manage.py runcommand, and control the start and stop of the service by writing a shell script, or manage it through supervisor.

If you want the background process to start and stop at the same time as the Web service, then putting it in wsgi.py is a good choice. Initialize the relevant background service in wsgi.py and start it. However, this approach is not flexible enough. When the Web service or background service needs to be updated separately, both need to be restarted. However, using the first method, one of the services can be updated separately.

The above is the detailed content of How to deploy Django. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete