我试图在Docker容器中设置我的Django 1.11应用程序。这是我到目前为止所做的总结:
docker-compose build
无问题地运行。X-CSRFToken
自定义标头。使用runserver
运行Django时,此方法正常。docker-compose.yml
中定义的虚拟主机添加到我的/etc/hosts
。dev.mysite.com
设置中设置虚拟主机名(ALLOWED_HOSTS
)。此时,我使用docker-compose up
运行Docker设置,并使用虚拟主机(dev.mysite.com
)在浏览器中访问我的网站。它适用于正常的GET请求,但后续的ajax POST请求在CSRF验证时失败,并出现以下CSRF失败原因:
CSRF token missing or incorrect.
原始响应具有SET-COOKIE
标头,其csrf标记与后面的ajax请求包含的X-CSRFToken
标头匹配。 ajax POST请求也设置了csrf cookie,该cookie也匹配第一个请求的SET-COOKIE
标头。
此时,我不知道为什么CSRF令牌没有在Django的csrf中间件中进行验证,我特别困惑,因为它可以正常使用Django的runserver命令,甚至可以使用提供用于https测试的ssl证书时django-extensions
的{{1}}命令。
这是我的runserver_plus
文件:
docker-compose.yml
Dockerfile:
version: '3'
services:
django-app:
build:
context: .
dockerfile: Dockerfile
args:
DJANGO_ENV: ${DJANGO_ENV}
environment:
- VIRTUAL_HOST=dev.mysite.com
- VIRTUAL_PROTO=uwsgi
restart: always
ports:
- "8000:8000"
redis:
image: redis:latest
restart: always
sysctls:
- net.core.somaxconn=1024
volumes:
- ./data/redis:/data
command: redis-server --appendonly yes
nginx-proxy:
image: jwilder/nginx-proxy:alpine
ports:
- "80:80"
environment:
- ENABLE_IPV6=true
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /etc/nginx/vhost.d
- /usr/share/nginx/html
- ./config/certs:/etc/nginx/certs:ro
devdocker.ini:
FROM python:3.6
RUN apt-get update && \
apt-get install -y && \
pip install uwsgi
ARG DJANGO_ENV=devdocker
ENV DJANGO_ENV=$DJANGO_ENV
ENV UWSGI_INI=/opt/mysite/config/uwsgi/${DJANGO_ENV}.ini
ENV DOCKER_CONTAINER=1
ENV UWSGI_ENV=DJANGO_SETTINGS_MODULE=mysite.settings.${DJANGO_ENV}
RUN echo $DJANGO_ENV
COPY . /opt/mysite
WORKDIR /opt/mysite
RUN pip install -r /opt/mysite/requirements/${DJANGO_ENV}.txt
RUN python manage.py collectstatic --no-input --settings=mysite.settings.${DJANGO_ENV}
ENV PYTHONUNBUFFERED=0
EXPOSE 8000
CMD ["sh", "-c", "uwsgi", "--ini", "${UWSGI_INI}"]
设置ajax发布请求(来自Django's docs):
[uwsgi]
socket = 0.0.0.0:8000
chdir = /opt/mysite
module = mysite.wsgi
static-map = /static=/opt/mysite/static
master = 1
processes = 2
threads = 2
请注意,我在devdocker环境的django设置中有function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
,以及将redis用作会话存储的所有正确设置。另请注意除csrf验证之外的所有内容都有效; GET请求适当返回,静态文件显示正常。