Django中間件解決跨域問題

由於瀏覽器同源策略的限制(同一主機不同端口之間),會產生客戶端向服務端請求存在跨域的問題,如向服務端發送獲取數據的請求,客戶端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div id="app">
    <button @click="getUser">獲取用戶信息</button>
    <ul>
        <li v-for="(item,index) in users">{{item}}</li>
        <li v-for="(item,index) in users">{{item.id}}</li>
        <li v-for="(item,index) in users">{{item.name}}</li>
        <li v-for="(item,index) in users">{{item.register_date}}</li>
    </ul>
</div>
</body>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            apiDomain: 'http://localhost:8000/api/v1',
            users: []
        },
        methods: {
            getUser() {
                let self = this
                axios.get(`${this.apiDomain}/user/`).then(function (response) {
                    self.users = response.data.data
                    console.log(response)
                }).catch(function (error) {
                    console.log(error)
                })
            }
        }
    });
</script>
</html>

在這裏插入圖片描述
服務端:

from rest_framework import views, serializers, response
from .. import models

class UserSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=5, error_messages={'max_length': '字段太長!'})
    register_date = serializers.DateTimeField(format='%Y-%m-%d %X')

    class Meta:
        model = models.User
        fields = ('name', 'register_date', 'id')

class User(views.APIView):
    def get(self, request):
        qs = models.User.objects.all().first()
        serializer = UserSerializer(qs, many=False)
        return response.Response({
            'status': 0,
            'data': serializer.data
        })

當點擊獲取數據的按鈕後,報錯:
在這裏插入圖片描述
這時候可以在Django中寫中間件,通過修改 response的屬性允許這個域的請求 來解決:

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_response(self, request, response):
        response['Access-Control-Allow-Origin'] = '*'
        return response

記得需要在配置文件中配置這個中間件:

MIDDLEWARE = [
	...
    'app.middle.M1'
]

這個時候就可以成功獲取數據:
在這裏插入圖片描述
在這裏插入圖片描述
再看下提交數據的請求:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div id="app">
    <button @click="getUser">獲取用戶信息</button>
    <button @click="createUser">創建用戶信息</button>
    <ul>
        <li v-for="(item,index) in users">{{item}}</li>
        <li v-for="(item,index) in users">{{item.id}}</li>
        <li v-for="(item,index) in users">{{item.name}}</li>
        <li v-for="(item,index) in users">{{item.register_date}}</li>
    </ul>
</div>
</body>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            apiDomain: 'http://localhost:8000/api/v1',
            users: []
        },
        methods: {
            getUser() {
                let self = this
                axios.get(`${this.apiDomain}/user/`).then(function (response) {
                    self.users = response.data.data
                    console.log(response)
                }).catch(function (error) {
                    console.log(error)
                })
            },
            createUser() {
                let self = this
                axios.post(`${this.apiDomain}/user/`, {"name": 'Thanlon'}).then(function (response) {
                    console.log(response)
                }).catch(function (error) {
                    console.log(error)
                })
            }
        }
    });
</script>
</html>

發送POST請求提交數據的時候,客戶端報錯竟然也報跨域問題。根據報錯提示,這是不允許請求頭引起的,所以需要配置允許的請求頭Access-Control-Allow-Headers:
在這裏插入圖片描述
並且服務端報錯:
在這裏插入圖片描述
這是因爲一般跨域會出現預檢請求,瀏覽器會認爲這是一次複雜的請求,會先發一個請求做預檢。預檢請求響應的狀態是200的時候纔會發真正的請求。所以,還需要在 中間件中設置允許的方法

from django.utils.deprecation import MiddlewareMixin

class M1(MiddlewareMixin):
    def process_response(self, request, response):
    	# 允許請求的域
        response['Access-Control-Allow-Origin'] = '*'
        # 允許請求的請求頭
        response['Access-Control-Allow-Headers'] = '*'
        # 允許請求的方法,適用*是允許所有,還可以指定。需要用都好隔開,例如'OPTIONS,GET,POST',實測發現這裏不需要也是可以的
        # response['Access-Control-Allow-Methods'] = 'OPTIONS'
        return response
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章