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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章