How to deploy Django?

11-09-2023

PART 1. Safety 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 POST came into contact with Django found that the form they had written was wrong when posting. After some searching, it was found that it was a problem with CSRF TOKEN, and then all the CSRF TOKEN configurations in settings.py were removed according to the online method, and the code ran normally. I don't know that this kind of operation will greatly affect the security of the website and increase the cost of repairing loopholes in the later period; The lowest cost is to eliminate security problems in the development stage.

Because the official document has explained the relevant contents of CSRF TOKEN in detail, I will not repeat the specific usage here. Here we recommend a more convenient usage, which is less sensitive to developers during development and does not need to pay special attention to whether the Token has been sent successfully.

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

In this way, all non-GET|HEAD|OPTIONS|TRACE requests initiated through AJAX in JQuery will automatically contain CSRF TOKEN (some codes for obtaining CSRF TOKEN are not listed). If other HTTP libraries or Fetch are used, you can set them accordingly.

1.2 API security design In some cases, our Web service will also provide some API services for other systems to call. For these API interfaces, CSRF must be closed, otherwise it will not work normally at all. We should also take other security measures to prevent the API interface from being abused. In addition to the normal passing parameters, we should ensure that these parameters are not tampered with by the middleman, and only those with authority are allowed to call the corresponding interface. For this reason, we need to introduce several passing parameters: timestamp, sign, access _ key, access _ token.

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

According to the business requirements, the precision of time stamp can be selected in seconds or milliseconds. The main purpose of adding a timestamp is to prevent this call from being replayed. The server should check whether the timestamp passed by the client is within a time range, and the overtime timestamp should be considered as an illegal request. In order to ensure the authenticity of the parameter, another parameter sign needs to be introduced, because even if the timestamp is replayed, there is still the 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 a little, sign needs to be regenerated to ensure the authenticity of the parameters. A common set of algorithms is to sort the parameter value according to the alphabetical order of the parameter key, and connect all the parameters with a specific separator, then calculate the hash and pass the sign parameters to the server. For example, the existing parameter AK = 2222 & at = 1111 & amp timestamp = 3333 & key 1 = AAA, after sorting alphabetically, it is 22221111aaa3333, after adding the separator (|), it is 2222(|)1111(|)aaa(|)3333, and then. Writing in Python code is relatively simple:

1.3 Miscellaneous items Apart from the above two important points, there are still some places that need extra attention.

Turn off DEBUG mode in production environment;

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

Set ALLOWED_HOSTS;;

Use ORM provided by Django as much as possible, and avoid directly executing SQL statements through methods such as. raw (). If it is unavoidable, the parameters must be escaped correctly to avoid SQL injection loopholes.

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

PART 2. How to deploy code pulled from git, install project dependencies using pip, and run services through manage.py, all of which look beautiful, but are you really going to do this in a production environment? 2.1 isolation environment in general, there will only be one Python environment on our server. When deploying, we usually install the dependencies needed by the project through pip, and these packages will be installed in the global site-packages directory.

When multiple projects are deployed, it is easy to cause dependency conflicts by adopting this way of installing dependencies. To give a simple example, we now have two projects, Project-A and Project-B. Both A and B rely on different versions of the third-party package third-A. When we passed pip install -r requirements-a.txt, the dependency Third-A was installed in 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 two projects depend on are inconsistent, for example, Project A needs version 1.0 and Project B needs version 2.0, there will be dependency conflicts, which will lead to the failure of installation dependency.

So how to solve this problem? It is easy for us to think that if we have multiple isolated environments that are unrelated to each other and each project is deployed in an independent environment, then this problem will be solved. Virtualenv was born to solve this problem. It can create a separate running environment for each project, thus avoiding the problem of dependency conflict.

2.2 Version Management Earlier, we knew how to create an isolated environment and deploy different projects in different environments, but there is a problem here. All environments use the same Python version. If it happens that you need to deploy several different versions of Python projects, such as Python2.7 (I know this version will not be maintained soon, but I will give you an example here), Python3.6 and Jython projects, it will be a bit complicated to install one by one, and even a compilation parameter is accidentally missing when compiling and installing, which will increase the deployment workload to some extent.

We can manage the problems of multiple Python versions by using pyenv, and further manage the problems of multiple Python versions and multiple virtual environments through the plug-in pyenv-VirtualEnv.

2.3 Gateway Interface When we have solved various environmental problems, it is time to consider how to run the project. If you are thinking of Python manage. PyrunServer 0.0.0.0: 80, it is a bit too simple.

Django has built a simple WSGI implementation for us to start the Web service in the above way. If you just want to debug or provide a small program that only serves a few people, it is an alternative, although it doesn't look so elegant.

If you really want to deploy the application to the actual production environment, then you need a high-performance WSGI Server instead of the simple WSGI Server provided by django. Gunicorn and uWSGI are both mainstream WSGI Server. According to the actual deployment environment, just choose one of them.

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 with uWSGI, and there are no 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. It should also be noted that if you want to deploy on Windows, you may need to use Apache+mod_wsgi.

2.4 Reverse Proxy When our WSGI Server is ready to start, we should consider the problem of reverse proxy. The reason why a layer of Nginx is blocked in front for reverse proxy is as follows:

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, because Django will not take the initiative to handle these requests, which need Nginx's help.

Nginx is used to balance the load of multiple backend. If your service is deployed on multiple servers, or one server is deployed for standby, these can be realized by simple settings on Nginx;

Exposing uWSGI or Gunicorn directly has certain security risks, so it will be more convenient to use Nginx to deal with HTTP.

In addition, there are some reasons not listed here, or the above sentence, if your service is simple and only a few people visit, you don't need to make such complicated settings.

2.5 Process Guarding Up to now, we have successfully deployed the service and can start providing the service normally. But we have neglected that if our Django unfortunately quits for some unknown reason, then our Web service will become 502. In order to ensure the stability of the service, we need to guard the Django process, and when it exits abnormally due to an unknown problem, we need to automatically pull up the required process.

Using supervisor as a monitoring tool can ensure the stable survival of Django process. It should be noted that the vulnerability of Supervisord remote command execution should be carefully avoided to avoid more serious accidents.

PART 3. Background service Generally speaking, if you want to start the background service, celery is a universal choice, but many times we don't want to introduce such a heavy dependence, so we need to find a way to start the background service ourselves.

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

If you want the background process to start and stop at the same time with the Web service, it is a good choice to put it in wsgi.py. Initialize the related background service in wsgi.py and start it. However, this approach is not flexible enough. When you need to update the Web service or the background service separately, you need to restart them all, and in the case of adopting the first method, you can update one of the services separately.

Copyright Description:No reproduction without permission。

Knowledge sharing community for developers。

Let more developers benefit from it。

Help developers share knowledge through the Internet。

Follow us