1. 程式人生 > >Django - - 進階 - - AJAX向Django後端提交POST請求

Django - - 進階 - - AJAX向Django後端提交POST請求

目錄

  • ajax登入示例
  • CSRF跨站請求偽造

1,ajax登入示例

  • urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login_ajax/$', views.login_ajax, name='login_ajax'),
    url(r'^index/$', views.index, name='index'),
]
  • views.py
from django.shortcuts import render, HttpResponse, redirect
import json
 
 
def index(request):
    return HttpResponse('this is index')
 
 
def login_ajax(request):
    if request.method == "POST":
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        ret = {"status": 0, 'url': ''}
        if user == "alex" and pwd == "123":
            ret['status'] = 1
            ret['url'] = '/index/'
        return HttpResponse(json.dumps(ret))
 
    return render(request, "login_ajax.html")
  • login_ajax.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登入</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/signin.css">
</head>
<body>
 
<div class="container">
 
    <form class="form-signin" action="{% url 'login' %}" method="post">
        {% csrf_token %}
        <h2 class="form-signin-heading">請登入</h2>
        <label for="inputUser" class="sr-only">使用者名稱</label>
        <input type="text" id="inputUser" class="form-control" placeholder="使用者名稱" required="" autofocus="" name="user">
        <label for="inputPassword" class="sr-only">密碼</label>
        <input type="password" id="inputPassword" class="form-control" placeholder="密碼" required="" name="pwd">
        <div class="checkbox">
            <label>
                <input type="checkbox" value="remember-me"> 記住我
            </label>
        </div>
        <input class="btn btn-lg btn-primary btn-block" id="login" value="登陸">
    </form>
 
</div> <!-- /container -->
 
 
<script src="/static/jquery-3.3.1.min.js"></script>
<script>
 
    $('#login').click(function () {
        $.ajax({
            url: '/login_ajax/',
            type: 'post',
            data: {
                csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
                user: $('[name="user"]').val(),
                pwd: $('[name="pwd"]').val()
            },
            success: function (data) {
                data = JSON.parse(data);
                if (data.status) {
                    window.location = data.url
                }
                else {
                    alert('登陸失敗')
                }
            }
        })
    })
</script>
 
</body>
</html>
  • 靜態檔案需要配置,使用了jQuery和Bootstrap。

2,CSRF跨站請求偽造

2.1 方式一

  • csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val() 放在POST的請求體中。
  • 示例中就是使用的這種方式。

2.2 方式二

  • 給ajax的請增加X-CSRFToken的請求頭,對應的值只能是cookie中的csrftoken的值。
  • 所以我們要從cookie中提取csrftoken的值,jQuery不能去cookie,我們使用jquery.cookie的外掛。點選下載jquer.cookie外掛:http://github.com/carhartl/jquery-cookie/zipball/v1.4.0
  • HTML中匯入jquery.cookie.js。
<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
 
    $('#login').click(function () {
        $.ajax({
            url: '/login_ajax/',
            type: 'post',
            headers:{ "X-CSRFToken":$.cookie('csrftoken') },
            data: {
                user: $('[name="user"]').val(),
                pwd: $('[name="pwd"]').val()
            },
            success: function (data) {
                data = JSON.parse(data);
                if (data.status) {
                    window.location = data.url
                }
                else {
                    alert('登陸失敗')
                }
            }
        })
    })
</script>

2.3 方式三

  • 使用 $.ajaxSetup() 給全域性的ajax新增預設引數。

  • 可以按照方式一設定data,也可以按照方式二設定請求頭。

$.ajaxSetup({
    data: {
        csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
    }
});
$.ajaxSetup({
    headers: {"X-CSRFToken": $.cookie('csrftoken')},
});

2.4 方式四

  • 官方推薦方法(用到jquery.cookie外掛):
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", $.cookie('csrftoken'));
        }
    }
});