背景

  • 在本地运行Django后端相信作为一个Django开发者来说不是问题了,但在完成项目后如何将我们的劳动成果部署在服务器上,则需要一番操作,本文使用nginx+uwsgi+django来搭建后端环境,服务器系统版本是centos7.2,使用的是root用户(并不推荐)

步骤

  1. 安装nginx yum install nginx,如果你没有办法通过这条命令安装ngin,请自行百度寻找原因

  2. 查询80端口是否被占用 netstat -tlnp|grep 80,如果有程序占用则kill掉 kill xxx

  3. 启动nginx /usr/sbin/nginx,在浏览器访问自己的服务器ip,如果出现下图则表示nginx启动成功

  4. 安装uwsgi,注意uwsgi是python的一个库,所以使用pip进行安装 pip install uwsgi --no-cache-dir,如果安装uwsgi报错请百度

  5. 新建一个django项目hello(或者使用现有的项目),首先验证项目能否正常访问:python manage.py runserver 0.0.0.0:8000后访问服务器ip:8000。然后停止运行django项目。

  6. 假设该项目目录为/root/hello,尝试使用uwsgi运行服务 uwsgi --http :8008 --chdir /root/hello --wsgi-file hello/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:8000,此时在浏览器输入ip:8008,出现Django欢迎界面表示uwsgi+django成功
    常用选项如下:

    • |参数|描述|
      |-|-|
      |http|协议的类型与端口号
      |processes|开启的进程的数量
      |workers|开启的进程数量,等同于processes
      |chdir|指定运行目录
      |wsgi-file|载入wsgi-file,相对路径
      |stats|在指定的地址上,开启状态服务
      |threads|每个worker运行的线程。
      |master|允许主进程存在(enable master process)
      |daemonize|使进程在后台运行,并将日志打到指定的日志文件
      |pidfile|指定pid文件的位置,记录主进程的pid号
      |vacuum|当服务器退出的时候自动清理环境,删除pid文件

    • 由于参数很多,我们可以将它们写入到一个配置文件中,任意位置新建uwsgi.ini文件,内容如下,然后运行 uwsgi --ini /root/uwsgi/uwsgi.ini,同样在浏览器测试输入ip:8000查看是否成功

      1
      [uwsgi]
      2
      # 这里由于是使用浏览器进行测试,使用http协议,之后改为socket
      3
      http = :8000    
      4
      chdir = /root/hello
      5
      wsgi-file = hello/wsgi.py
      6
      module = hello.wsgi
      7
      master = true        
      8
      processes = 4
      9
      threads = 2
      10
      vacuum = true
      11
      # uwsgi进程号
      12
      pidfile = /root/uwsgi/uwsgi.pid 
      13
      # 存放日志文件路径
      14
      daemonize = /root/uwsgi/uwsgi.log
  7. 修改nginx配置文件 /etc/nginx/nginx.conf,并保存,修改之前写的uwsgi.ini中的http为socket,保存

    1
    ...
    2
    3
    http {
    4
        ...
    5
    6
        server {
    7
            listen      80;
    8
            server_name   xxx; # 服务器域名或ip
    9
            
    10
            location / {
    11
                include uwsgi_params;
    12
                #这行指定uwsgi开放的数据交换接口
    13
                uwsgi_pass 127.0.0.1:8000;
    14
                #这里与配置uwsgi的ini文件中module内容一致
    15
                uwsgi_param UWSGI_SCRIPT hello.wsgi;
    16
                #这里与配置uwsgi的ini文件中chdir内容一致
    17
                uwsgi_param UWSGI_CHDIR  /root/hello;      
    18
            }
    19
    20
    21
            location /static {
    22
                root /root/hello/static;
    23
            }
    24
    25
            error_page 404 /404.html;
    26
                location = /40x.html {
    27
                
    28
            }
    29
    30
            # error_page 500 502 503 504 /50x.html;
    31
            #     location = /50x.html {
    32
                
    33
            # }
    34
        }
    35
    }
  8. 关闭之前打开的uwsgi和nginx进程(确认80端口和8000端口无进程占用),运行命令 uwsgi --ini /root/uwsgi/uwsgi.ini & /usr/sbin/nginx,在浏览器访问 http://ip,看到django页面即成功

后期运维

  1. nginx 日志文件位于/var/log/nginx/目录下

  2. uwsgi 日志文件自定义于uwsgi.ini文件的daemonize字段

  3. 每次修改nginx.conf配置文件需要重启服务

SSL证书

原理

  1. 证书包含以下信息

    • 证书的发布机构
    • 证书的有效期
    • 公钥
    • 证书所有者
    • 签名所用的算法,即加密算法,配合公钥用于加密明文
    • 指纹及其指纹算法。指纹用于确保证书没有被修改过,原理就是发布者在发布证书的同时根据指纹算法计算证书的hash值并和证书放在一起,使用者在使用证书的时候也计算一下hash,如果对的上证明没被修改过。注意,这个指纹与算法使用了CA证书机构的私钥用签名算法加密了后才和证书放在一起
  2. 请求过程
    图2

    1. 客户端向一个https网站发出请求

    2. 服务器将证书发给客户端进行校验,证书包含了其公钥。这里说明一下客户端怎么验证证书有效

      1. 首先在本机寻找是否有这个证书上的ca的根证书,如果有继续下一步。没有则警告
      2. 使用ca根证书的公钥对服务器证书的指纹和算法进行解密
      3. 得到指纹算法后,用这个指纹算法计算一遍证书的摘要获得指纹
      4. 将计算出的指纹与证书带的指纹做对比
    3. 校验成功后,客户端会生成一个随机串(对称加密的密钥)使用证书的公钥加密后发送给服务器

    4. 服务器用自己的私钥解密得到这个随机串(对称加密的密钥)

    5. 此后使用这个随即串进行对称加密

  3. 为什么不一直使用非对称加密而要生成一个对称加密的密钥

    • 非对称加密的效率比对称加密低

HTTPS中间人攻击

图4
图4
  • 中间人截取客户端发送给服务器的请求,然后伪装成客户端与服务器进行通信;将服务器返回给客户端的内容发送给客户端,伪装成服务器与客户端进行通信。 通过这样的手段,便可以获取客户端和服务器之间通信的所有内容。

  • 使用中间人攻击手段,必须要让客户端信任中间人的证书,如果客户端不信任,则这种攻击手段也无法发挥作用。

配置

  • 在nginx.conf中添加如下规则即可

    1
    server {
    2
        listen         443 ssl;
    3
        server_name  domain.com;
    4
    5
        charset 'utf-8';
    6
    7
        #证书文件
    8
        ssl_certificate     xxx.crt;
    9
        #私钥文件
    10
        ssl_certificate_key xxx.key;
    11
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    12
        ssl_ciphers         HIGH:!aNULL:!MD5;
    13
    14
        ...
    15
    }