霍克依毒间

导航

 

今天在尝试调用jQuery的ajax时发现一个问题,就是使用GET方法服务器可以正常返回,但是使用POST方法却不行。后来再测试表单方式的POST的方法也不行。只要POST必报HTTP 403错误!非常奇怪。。。

      在网上搜了一大堆资料以后原来是因为Django的Cross Site Request Forgery protection机制的问题。这个机制是为了保护不受csrf攻击。什么是crsf攻击,桃林博客中有一段较为浅显的讲解。解决方案其实Django的已经给出http://docs.djangoproject.com/en/dev/ref/contrib/csrf/,根据说明修改后,ajax可以顺利Post了。

      方法其实很简单,首先解决表单的POST。在settings.py文件中找到 MIDDLEWARE_CLASSES,在其中加入一个中间件:'django.middleware.csrf.CsrfViewMiddleware' ,修改后的代码如下:

Python代码

  1. MIDDLEWARE_CLASSES = (
  2.     'django.middleware.common.CommonMiddleware',
  3.     'django.contrib.sessions.middleware.SessionMiddleware',
  4.     'django.middleware.csrf.CsrfViewMiddleware',
  5.     'django.contrib.auth.middleware.AuthenticationMiddleware',
  6.     'django.contrib.messages.middleware.MessageMiddleware',
  7.     'django.middleware.csrf.CsrfResponseMiddleware', #加入这个中间件
  8. )
复制代码

经过这番修改,可以解决表单方式的POST提交HTTP 403问题了。ajax的Post提交仅这样改还不行。还需要钩上一个每次提交时的cookie处理过程。也就是每次提交的时候,都触发这个过程,在提交的http头上加入csrf token。不过还好,如果你是用jQuery来处理ajax的话,Django直接送了一段解决问题的代码。把它放在一个独立的js文件中,在html页面中都引入即可。注意这个js文件必须在jquery的js文件引入之后,再引入。代码我直接复制过来了,如下:

   

Js代码

  1. $('html').ajaxSend(function(event, xhr, settings) {
  2.     function getCookie(name) {
  3.         var cookieValue = null;
  4.         if (document.cookie && document.cookie != '') {
  5.             var cookies = document.cookie.split(';');
  6.             for (var i = 0; i < cookies.length; i++) {
  7.                 var cookie = jQuery.trim(cookies[i]);
  8.                 // Does this cookie string begin with the name we want?
  9.                 if (cookie.substring(0, name.length + 1) == (name + '=')) {
  10.                     cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
  11.                     break;
  12.                 }
  13.             }
  14.         }
  15.         return cookieValue;
  16.     }
  17.     if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
  18.         // Only send the token to relative URLs i.e. locally.
  19.         xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  20.     }
  21. });

经过这番折腾,算是可以正常用ajax与Django通信了。

posted on 2012-06-23 12:14  霍克依毒间  阅读(450)  评论(0编辑  收藏  举报