# 6、Django设置csrf\_token

## Ajax请求设置csrf\_token

### 方式一

**通过获取隐藏的input标签中的csrfmiddlewaretoken值，放置在data中发送。**

```js
$.ajax({
    url: "/cookie_ajax/",
    type: "POST",
    data: {
        "username": "yang",
        "password": 123,
        // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data总
        "csrfmiddlewaretoken": $("[name="csrfmiddlewaretoken"]").val()
    },
    success: function(data){
        console.log(data);
    }
})
```

### **方式二**

通过获取返回的cookie中的字符串,放置在请求头中发送。

注意: 需要引入一个jquery.cookie.js插件。

```js
$.ajax({
    url: "/cookie_ajax/",
    type: "POST",
    // 从Cookie取csrftoken, 并设置到请求头中
    headers: {"X-CSRFToken": $.cookie("csrftoken")},
    data: {
        "username": "yang",
        "password": 123
    },
    success: function(data){
        console.log(data)
    }
})
```

或者用自己写一个getCookie方法：

```js
function getCookie(name){
    var cookieValue = null;
    if (document.cookie && document.cookie !== ""){
        var cookies = document.cookie.split(";");
        for (var i = 0; i < cookies.length; i++){
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + "=")){
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie("csrftoken");
```

每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。

```js
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);
        }
    }
})
```

如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。

如果你的视图渲染的HTML文件中没有包含

, Django可能不会设置CSRFtoken的cookie。

这个时候需要使用ensure\_csrf\_cookie()装饰器强制设置Cookie。

```python
django.views.decorators.csrf import ensure_csrf_cookie
 
@ensure_csrf_cookie
def login(request):
    pass
```

## 如何取消 csrf\_exempt

### 基于类

在Django中对于基于函数的视图我们可以 @csrf\_exempt 注解来标识一个视图可以被跨域访问。那么对于基于类的视图，我们应该怎么办呢？

简单来说可以有两种访问来解决

### 方法一：在类的 dispatch 方法上使用 @csrf\_exempt

```javascript
from django.views.decorators.csrf import csrf_exempt

class MyView(View):

    def get(self, request):
        return HttpResponse("hi")

    def post(self, request):
        return HttpResponse("hi")

    @csrf_exempt
    def dispatch(self, *args, **kwargs):
        return super(MyView, self).dispatch(*args, **kwargs)
```

### 方法二：在 urls.py 中配置

```javascript
from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt
import views

urlpatterns = [
    url(r'^myview/$', csrf_exempt(views.MyView.as_view()), name='myview'),
]
```

### 基于视图

```python
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt()
def demo1(request):
    return render(request,'xx.html')
```
