django中的跨域问题以及解决策略

目录


跨域请求

跨域是指浏览器不能执行其他网站的脚本, 它是由浏览器的同源策略造成的,,是浏览器对javascript 实施的安全限制。 

浏览器从一个域名的网页请求去另一个域名的资源时,出现域名,端口,协议任意一个不同就属于跨域

django中的跨域问题以及解决策略

部署时前后端不分离可以解决此问题【但是不推荐】

django中的跨域问题以及解决策略

同源策略

同源策略是浏览器为了保护用户信息安全的一种安全政策。 指的是iu篮球页面的协议, 域名,端口号都相同,其目的是为了保证用户的信息安全,防止恶意网站盗取数据信息。 

不同源的客户端脚本js在没有得到服务端的明确授权的情况下,浏览器会显示拒绝提供服务给前端ajax/axios。

CORS(跨域资源共享)简介

CORS是一个W3C标准,全程跨域资源共享。 它允许浏览器向跨源的后端服务器发出ajax请求,

从而克服了AJAX只能同源使用的限制。

实现CORS主要一开后端服务器响应数据中设置响应头信息返回的CORS需要浏览器和服务器同时支持, 目前除了IE浏览器都支持该功能

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信

容易混淆的点:

  • CORS:跨域资源共享
  • CSRF: 跨站请求伪造
  • XSS: 跨站脚本攻击

CORS基本流程

浏览器讲CORS请求分成两类: 简单请求(simple request) 和 非简单请求(not-so-simple-request)

浏览器发出CORS简单请求只需要在头信息中增加Origin字段

浏览器发出非简单CORS请求, 会在正式通信之前增加一次Http查询请求,即’预检‘请求。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之内,以及跨源使用那些Http动词和头信息字段

只有的带肯定答复,溜啦冷凝器才会发出正式的XMLHttpRequest请求,否则就会报错。 

解决跨域问题的方法

前端: 通过代理解决

nginx代理

cors解决跨域:django-cors-headers

CORS两种请求详解

只需要同时满足一下两大条件,就属于简单请求

1. 请求方式是一下三种

  • HEAD
  • GET
  • POST

2, Http的头部信息不能超出以下几种字段

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是不能同时满足以上两个条件就属于非简单请求

json格式是非简单请求

浏览器对这两种请求的处理是不一样的

简单请求和非简单请求的区别

简单请求:之发送一次请求

非简单请求: 发送2次请求,在发送数据之前会先发一次请求用于做’预检‘看后端是否允许,只有预检通过之后才会再次发送请求用于数据传输

请求方式OPTIONS

预检:

如果非简单请求是PUT等请求, 则服务端需要设置允许某请求,否则预检不通过

  • Access-Control-Request-Method

如果非简单请求设置了请求头, 则服务端需要设置允许某请求头,否则预检不通过

  • Access-Control-Request-Headers

解决跨域问题(服务端)

简单请求

Django项目: apps/user/views.py

from django.http import JsonResponse


def test(request):
    obj = JsonResponse({'name': 'darker', 'age': '18'})
    # 值针对简单请求
    obj['Access-Control-Allow-Origin'] = '*'    # 允许所有IP访问
    return obj

2, 原 django项目: apps/user/urls.py

from django.urls import path
from user import views

urlpatterns = [
    path('test/', views.test),
]

3. django项目中注释掉dev.py中的CSRF

4, 再创建一个django项目(用另一个端口)

template中创建index。html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<button id="btn">点我</button>

</body>
<script>
    $('#btn').click(function () {
        $.ajax({
            url: 'http://127.0.0.1:8000/user/test/',
            method: 'get',
            success: function (data) {
                console.log(data)
            }
        })
    })
</script>
</html>

views.py

from django.shortcuts import render


def index(request):
    return render(request, 'index.html')

urls.py

from django.urls import path
from app01 import views

urlpatterns = [
    path('test/', views.index),
]

django中的跨域问题以及解决策略

 非简单请求

原django项目 app/user/view.py

from django.http import JsonResponse


def test(request):
    obj = JsonResponse({'name': 'Darker', 'age': '18'})
    if request.method == 'OPTIONS':
        obj['Access-Control-Allow-Headers'] = 'Content-Type,authorization'  # 或者填写 *
    obj['Access-Control-Allow-Origin'] = 'http://127.0.0.1:8002'    # 8002端口是当前项目的
    return obj

 新django项目中 template/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<button id="btn">点我</button>

</body>
<script>
    $('#btn').click(function () {
        let obj = {name: 'Darker'}
        $.ajax({
            url: 'http://127.0.0.1:8000/user/test/',
            method: 'post',
            contentType: 'application/json',
            headers: {authorization: 'Darker'},
            data: JSON.stringify(obj),
            success: function (data) {
                console.log(data)
            }
        })
    })
</script>
</html>

 3, 中间件处理

① 在原Django项目的根路径创建mymiddle.py – 自定义中间件

from django.utils.deprecation import MiddlewareMixin


class CoreMiddle(MiddlewareMixin):
    def process_response(self, request, response):
        if request.method == 'OPTIONS':
            response['Access-Control-Allow-Headers'] = 'Content-Type, authorization'    # 如果是 * 就代表全部IP都可以访问
        response['Access-Control-Allow-Origin'] = '*'
        return response

② 在原Django项目的dev.py的中间件中添加自定义中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'mymiddle.CoreMiddle',    # 这一句
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

③ 原Django项目apps/user/views中替换成如下代码

from django.http import JsonResponse


def test(request):
    return JsonResponse({'name': 'Darker', 'age': '18'})

解决跨域问题(第三方)

后端配置

① 后端安装跨域模块

pip install django-cors-headers

2, 到dev.py中注册

INSTALLED_APPS = (
    ...
    'corsheaders'
)

3  到dev.py中添加中间件

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',    # 这个是原本就存在的
    ...
]

④ 到dev.py中添加如下代码

CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = (
#     'http://127.0.0.1:8080',
# )
CORS_ALLOWED_ORIGINS_REGEXES=[
    r'^http://.*?$',
]
# CORS_ORIGIN_REGEXES_WHITELIST = (
#         r'^http://.*?$',
# )
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

 设置dev.pyALLOWED_HOSTS

ALLOWED_HOSTS = ['*']

后端测试

(测试 – 后台)到apps/user/views中替换成如下代码

from django.http import JsonResponse


def test(request):
    return JsonResponse({'name': 'Darker', 'age': '18'})

(测试 – 后台)到apps/user/urls中替换成如下代码

from django.urls import path
from user import views

urlpatterns = [
    path('test/', views.test),
]

启动项目

python manage.py runserver 127.0.0.1:8000

 访问测试

django中的跨域问题以及解决策略

前端测试

(测试 – 前台)App.vue 中换成如下代码

<template>
  <div id="app">
    <router-view/>
    {{name}}
  </div>
</template>

<script>
export default {
  data () {
    return {
      name: []
    }
  },
  mounted () {
    this.$axios.get(this.$settings.base_url + '/user/test/').then(res => {
      this.name = res.data
    })
  }
}
</script>

 启动项目

npm run serve

django中的跨域问题以及解决策略

解决跨域问题(前端)

前端App.vue

<template>
  <div id="home">
    <h1>我是主页</h1>
    <h2>{{info}}</h2>
  </div>
</template>

<script>
export default {
  name: 'Home',
  data () {
    return {
      info: []
    }
  },
  mounted () {
    this.$axios.get('/moreClassicList?sortId=1&showType=3').then(res => {
      console.log(res.data)
    })
  }
}
</script>

<style scoped>

</style>

前端项目根路径 vue.config.js

const webpack = require("webpack");

module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "window.jQuery": "jquery",
        "window.$": "jquery",
        Popper: ["popper.js", "default"]
      })
    ]
  },
  devServer: {
    proxy: {
      '/ajax': {
        target: 'https://m.maoyan.com/',
        changeOrigin: true
      },
      '/user': {
        target: 'http://127.0.0.1:8000',
        changeOrigin: true
      }
    }
  }
};

 wsgi,uWSGI,uwsgi

https://www.liuqingzheng.top/article/1/05-CGI,FastCGI,WSGI,uWSGI,uwsgi%E4%B8%80%E6%96%87%E6%90%9E%E6%87%82/

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2023年3月10日
下一篇 2023年3月10日

相关推荐