django.request: Forbidden (Referer 检查失败 - 没有Referer。)

Posted

技术标签:

【中文标题】django.request: Forbidden (Referer 检查失败 - 没有Referer。)【英文标题】:django.request: Forbidden (Referer checking failed - no Referer.) 【发布时间】:2016-07-04 22:54:22 【问题描述】:

我正在使用 AWS 和 Django Rest Framework 开发 Web 应用程序。(Django:v1.8, DRF:v3) 对于 POST 多部分表单请求,我一直收到 django.request: Forbidden (Referer checking failed - no Referer.)

我在我的 ec2(在自动缩放组中)和 Gunicorn 上使用 AWS ELB(弹性负载均衡器)、nginx

AWS ELB 监听器设置如下(仅限 HTTPS):

elb https only listener setting

NGINX 设置如下:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events 
    worker_connections 1024;


http 
    include         /etc/nginx/mime.types;
    default_type    application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;

    keepalive_timeout   65;
    types_hash_max_size 2048;

    include /etc/nginx/conf.d/*.conf;

    index   index.html index.htm;

    upstream my_server 
        server localhost:8000;
    

    server 

        listen       80;
        server_name  <server name>;
        access_log   /etc/nginx/log/local-wc.access.log;
        error_log    /etc/nginx/log/local-wc.error.log;
        root /usr/share/nginx/html;

        location /api/v1 
            proxy_pass          http://my_server/api/v1;
            proxy_redirect      off;
            proxy_set_header    Host            $host;
            proxy_set_header    X-Real-IP       $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Protocol $scheme;
        
    

&lt;server name&gt; 是指向 elb DNS 名称的 CNAME。

换句话说,&lt;server name&gt; => xxxx-123456789.us-west-2.elb.amazonaws.com(记录)。 每个 API 调用都是由 https://&lt;server name&gt;/api/v1/* 进行的

Gunicorn 终于运行了: gunicorn my_django_app.wsgi:application -w 1 -b 127.0.0.1:8000 -t 300 --max-requests=100

而 Django 设置是:

ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

查看功能如下(CSRF除外):

class UserViewSet(CsrfExemptMixin, mixins.CreateModelMixin,
              mixins.ListModelMixin,
              mixins.RetrieveModelMixin,
              mixins.UpdateModelMixin,
              viewsets.GenericViewSet):

    # already tried @csrf_exempt
    def create(self, request, *args, **kwargs):
        self.parser_classes = (FormParser, MultiPartParser, )
        .........

问题又来了:

当我发送时

curl -i -k -X POST -H "Accept: application/json" \
    -F "email=myemail@email.com" \
    -F "profile_img=@profile.jpg" \
    https://<server name>/api/v1/users/

在我的 Django 日志中:

[WARNING] django.request: Forbidden (Referer checking failed - no Referer.): /api/v1/users/

它适用于 HTTP 上的 POST 或 HTTPS 上的 GET 方法。

不知道是ELB配置错误还是Nginx配置错误和referer... 如果有人帮助我解决这个问题,我将不胜感激。。

【问题讨论】:

【参考方案1】:

我认为 DRF 忽略了 csrf_exempt 装饰器,我不确定 CsrfExemptMixin 的定义位置。您可以做的最简单的事情是将Referrer: yourhost 添加到您的 curl 标题中。

【讨论】:

像内置 React Native 这样的移动应用怎么样?

以上是关于django.request: Forbidden (Referer 检查失败 - 没有Referer。)的主要内容,如果未能解决你的问题,请参考以下文章

Python - Django - request 对象

django logging - django.request 记录器和额外的上下文

只有 Django request.body 包含数据(不是 request.POST)

django:request.bodyrequest.POSTrequest.data

django:request.bodyrequest.POSTrequest.data

模型中的 django request.GET