Django 在发送 POST 请求时返回 403 错误

Posted

技术标签:

【中文标题】Django 在发送 POST 请求时返回 403 错误【英文标题】:Django returns 403 error when sending a POST request 【发布时间】:2011-10-11 16:02:47 【问题描述】:

当我使用以下 Python 代码向我的 Django 网站发送 POST 请求时,我收到 403: Forbidden error。

url = 'http://www.sub.domain.com/'
values =  'var': 'test' 

try:
    data = urllib.urlencode(values, doseq=True)
    req = urllib2.Request(url, data)
    response = urllib2.urlopen(req)
    the_page = response.read()
except:
    the_page = sys.exc_info()
    raise

当我打开任何其他网站时,它可以正常工作。 domain.com 也是 Django 网站,它也可以正常工作。 我想,这是 Django 配置问题,谁能告诉我应该怎么做才能提供对我的脚本的访问权限?

【问题讨论】:

普通浏览器可以访问网页吗? 我可以从普通浏览器获取。我的服务器日志是空的,我没有足够的权限在我的主机上查看所有日志。 ***.com/a/30210391/940098 在 DRF 中,包括 permission_classes 在视图中起作用。例如:permission_classes = [permissions.IsAuthenticated] 【参考方案1】:

看这里https://docs.djangoproject.com/en/dev/ref/csrf/#how-to-use-it。

尝试使用@csrf_exempt 标记您的视图。这样,Django 的 CSRF 中间件将忽略 CSRF 保护。您还需要使用from django.views.decorators.csrf import csrf_exempt。见:https://docs.djangoproject.com/en/dev/ref/csrf/#utilities

请注意,通过在您的视图上禁用 CSRF 保护,您正在为 CSRF 攻击打开大门。

如果安全性对您至关重要,请考虑使用@csrf_exempt,后跟@requires_csrf_token(请参阅:https://docs.djangoproject.com/en/dev/ref/csrf/#unprotected-view-needs-the-csrf-token)。然后,在你的脚本中传递这个令牌,就是这样。

【讨论】:

非常感谢您分享以上两个链接。在添加这个 import 语句 from django.views.decorators.csrf import csrf_protect 并像 @csrf_exempt 这样豁免特定功能后,我的代码运行得非常好 再次感谢。【参考方案2】:

您发布的视图上是否有 Django 表单?如果是这样,我想知道它是否给出了 csrf 错误。我认为这表现为 403。在这种情况下,您需要添加 csrf_token 标签。只是一个想法。

【讨论】:

我在哪里添加该标签?如果在模板中 - 它不起作用。这是我的观点:dpaste.com/575405,t.html 只是 form 您能否更新原始问题以包含您的代码(视图、网址、表单)和 html,而不是链接到 dpaste? @Djent 为什么 t.html 只是一个 form 它包含在其他页面中?如果你只是放 form 它不是一个有效的网页,甚至不是一个有效的表单,因为 form 只是放置了你仍然需要在它周围添加表单标签的表单元素。 如果是 csrf 问题,您可以尝试在视图上禁用 csrf temporarliy,看看是否有效,如果有效,那么您就知道问题所在了。请参阅此文档以获取更多帮助。 docs.djangoproject.com/en/1.3/ref/contrib/csrf/#exceptions 正确答案。【参考方案3】:

响应是 403,因为 django 在您发出的每个 POST 请求中都需要一个 csrf 令牌(包含在发布数据中)。

有多种方法可以做到这一点,例如:

从cookie中获取token,方法已在文章中说明,请在此处输入链接描述

您可以使用模板中提供的 csrf_token 从 DOM 访问它

所以现在使用第二种方法:

var post_data = 
  ...
  'csrfmiddlewaretoken':" csrf_token "
  ...


$.ajax(
  url:'url',
  type:'POST'
  data:post_data,
  success:function(data)
    console.log(data);
  ,
  error:function(error)
    console.log(error);
  
);

【讨论】:

【参考方案4】:

或者您可以允许发出此帖子请求的权限。

注意:应该在您不需要验证用户在我们的服务器上发布任何内容的情况下使用,例如,当新用户首次注册时

from rest_framework.permissions import AllowAny

class CreateUser(APIView):
    permission_classes = (AllowAny,)
    def post(self, request, format=None):
        return(Response("hi"))

进一步注意,如果您想让该发布请求来自不同的域(如果应用程序的前端是 React 或 Angular 而后端是 Django),请确保在设置文件中添加以下内容:

    更新 INSTALLED_APPS 以使用“coreHeaders”:

    INSTALLED_APPS = [ 'corsheaders', ]

    通过再次将以下内容添加到设置文件中,将您的前端域列入白名单:

    CORS_ORIGIN_WHITELIST = ( '本地主机:8080', )

【讨论】:

【参考方案5】:

Django 文档提供了几种方法来确保包含 CSRF 令牌。详情请见https://docs.djangoproject.com/en/1.11/ref/csrf/。

【讨论】:

【参考方案6】:

当身份验证令牌过期或没有随请求发送令牌时,我收到此错误。使用更新的令牌解决了这个问题。

curl -X POST -H "Authorization: Token mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

curl -X POST -H "Authorization: JWT mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

取决于令牌类型。

【讨论】:

【参考方案7】:

我也有这个问题,因为我尝试使用'../url' URL Jumping 从另一个端点访问主端点。 我的解决方案是为同一视图集添加另一条路径;

router.register('main/url',ViewSet,'name');
router.register('secondary/url',ViewSet,'name')

但在您的情况下,您正试图从完全不同的位置访问它,从 Django 的角度来看,因此您需要使用 @crsf_exempt 中间件标记您的 ViewSet,这将禁用与 CRSF 相关的安全协议。

【讨论】:

以上是关于Django 在发送 POST 请求时返回 403 错误的主要内容,如果未能解决你的问题,请参考以下文章

django post请求 403错误解决方法

django post请求 403错误解决方法

Django的POST请求时因为开启防止csrf,报403错误,及四种解决方法

Django ajax post 403 问题

当我发送 POST 请求时被禁止 403

Django jquery ajax 返回403