Welcome to kimi's blog

vue-与后端交互--跨域请求

与后端交互

与后端交互统一使用json编码格式

与后端交互涉及到跨越问题和如何处理跨越问题?

当前端发送请求,后端响应了,但是前端还是报错,这是因为:跨域问题的存在,浏览器检测到前端和后端不是来自同一个,所以认为这是不安全的,所以就拦截了该资源的传递

想要解决这个问题,就要实现:CORS,也就是 跨域资源共享

http://photo.liuqingzheng.top/2023 02 15 18 46 15 /01 get.gif

跨域问题---响应头添加允许headers={'Access-Control-Allow-Origin':'*'}

浏览器的原因,只要不是向地址栏中的【域:地址和端口】发送请求,拿的数据,浏览器就给拦截了。

处理跨域问题

后端代码处理,只需要在响应头中加入允许即可

1. jquery发送ajax

点击查看代码
headers={'Access-Control-Allow-Origin':'*'}  
# 访问控制允许的源 设置为全部
# 路由
from django.urls import path,include
from app01 import views
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user',views.UserShow,'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/',include(router.urls))
]

# 视图类
from rest_framework.viewsets import ViewSetMixin,ViewSet,ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
# 采用CBV
class UserShow(ViewSet):

    @action(methods=['GET'],detail=False)
    def index(self,request):
        print('函数执行了')

        return Response(headers={'Access-Control-Allow-Origin':'*'},data={'name':'kiki','age':18,'gender':'female'})
       
        
# 页面分离
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
        <script src="vue.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>

</head>
<body>
<div class="app">
        <h1>加载用户信息</h1>
        <button @click="handleData">显示数据</button>
        <div v-if="age!=0">
            <p>用户名:{{ username }}</p>
            <p>年龄:{{ age }}</p>
            <p>性别:{{ gender }}</p>
        </div>
        <div v-else>
            无用户信息
        </div>
</div>

</body>
    <script>
        var vm = new Vue({
            el:'.app',
            data:{
                username:'',
                age:0,
                gender:'未知',
            },

            methods:{
                handleData(){
                 //1  学过的,jq的ajax
                    $.ajax({
                        url:'http://127.0.0.1:8000/api/v1/user/index/',
                        type:'get',
                        data:[],
                        success:data=>{
                            console.log(data)
                            this.username=data.name
                            this.age=data.age
                            this.gender=data.gender
                        }
                    })
                }

            }
        })
    </script>
</html>

2. fetch发送ajax请求

# fetch 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应
	-新的发送ajax 接口
    -用起来比较方便
    -支持promise写法[最新的异步写法]
    -解决了原生的XMLHttpRequest兼容性的问题
    -不是所有浏览器都支持
    -主流现在是用axios[第三方]发送请求
# XMLHttpRequest: 原生js提供的
	-比较老,不同浏览器需要做一些兼容性的处理,写起来比较麻烦
    -jq基于它做了封装
    
    
    
 # 发送ajax请求,
点击查看代码
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <title>Title</title>
           <script src="vue.js"></script>
       <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
   
   </head>
   <body>
   <div class="app">
           <h1>加载用户信息</h1>
           <button @click="handleData">显示数据</button>
           <div v-if="age!=0">
               <p>用户名:{{ username }}</p>
               <p>年龄:{{ age }}</p>
               <p>性别:{{ gender }}</p>
           </div>
           <div v-else>
               无用户信息
           </div>
   </div>
   
   
   
   </body>
       <script>
           var vm = new Vue({
               el:'.app',
               data:{
                   username:'',
                   age:0,
                   gender:'未知',
               },
   
               methods:{
                   handleData(){
                    //1  fetch
                       fetch('http://127.0.0.1:8000/api/v1/user/index/').then(response=>response).then(res=>{
                           console.log(res)
                           console.log('fetch')
                           this.username=res.name
                           this.age=res.age
                           this.gender=res.gender
                       })
                   }
               }
           })
       </script>
   </html>
   

3. Axios发送ajax请求

Axios是在Vue框架上,是第三方的模块, Axios 是一个基于 promiseHTTP 库,还是基于XMLHttpRequest封装的。

下载第三方模块

pip install axios

Axios发送ajax前后端交互

点击查看代码

   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <title>Title</title>
           <script src="vue.js"></script>
           <script src="axios.js"></script>
       <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
   
   </head>
   <body>
   <div class="app">
           <h1>加载用户信息</h1>
           <button @click="handleData">显示数据</button>
           <div v-if="age!=0">
               <p>用户名:{{ username }}</p>
               <p>年龄:{{ age }}</p>
               <p>性别:{{ gender }}</p>
           </div>
           <div v-else>
               无用户信息
           </div>
   </div>
   
   </body>
       <script>
           var vm = new Vue({
               el:'.app',
               data:{
                   username:'',
                   age:0,
                   gender:'未知',
               },
   
               methods:{
                   handleData(){
                    //1  axios
                       axios.get('http://127.0.0.1:8000/api/v1/user/index/').then(res=>{
                           console.log(res)
                           this.username=res.data.name
                           this.age=res.data.age
                           this.gender=res.data.gender
                       })
   
                   }
               }
           })
       </script>
   </html>


image

4. 电影--案例

官网:https://m.maizuo.com/v5/#/films/nowPlaying
image

点击查看代码
   # 视图类
   class UserShow(ViewSet):
       @action(methods=['GET'], detail=False)
       def film(self, request):
           # 打开文件
           with open('./film.json','r',encoding='utf-8')as f:
               f= json.load(f)
               print(f)
           return Response(headers={'Access-Control-Allow-Origin': '*'},
                           data=f)
   
   
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <title>Title</title>
           <script src="vue.js"></script>
           <script src="axios.js"></script>
       <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
   
   </head>
   <body>
   <div class="app">
           <h1>最近电影</h1>
           <button @click="handleData">显示电影</button>
       <ul>
           <li v-for=" i in dataList" >
               <h2>名字:{{ i.name }}</h2>
               <h3>导演:{{ i.director }}</h3>
               <h3>类型:{{ i.category }}</h3>
               <p>简介:{{ i.synopsis }}</p>
               <img :src="i.poster" alt="" height="300px" width="200px">
           </li>
       </ul>
   
   </div>
   </body>
       <script>
           var vm = new Vue({
               el:'.app',
               data:{
                   dataList:[]
               },
   
               methods:{
                   handleData(){
                    //1  axios
                       axios.get('http://127.0.0.1:8000/api/v1/user/film/').then(res=>{
                           console.log(res)
                           this.dataList=res.data.data.films
                           console.log(this.date)
   
                       })
                   },
                   //直接加载
                    created() {
               // this.handleClick()
               axios.get('http://127.0.0.1:8000/api/v1/user/film/').then(res => {
                   this.dataList = res.data.data.films
               })
   
           }
               }
           })
       </script>
   </html>

image

跨域请求--CORS两种请求

CORS基本流程
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

跨域问题详解

前端发送ajax请求,后端会有跨域的拦截,原因是:同源策略。同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

-请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
-发送ajax请求的地址,必须跟浏览器上的url地址处于同域上 域[域名,地址,端口,协议]
-请求成功,数据库返回,但是浏览器拦截


# 补充:浏览器中输入域名,没有加端口
	-www.baidu.com---->dns--->解析成地址  192.168.2.3----》没有加端口,默认是80
    -dns解析,先找本地的host文件
    	-可以修改本地的host做映射

image

如何解决跨域问题?

  1. CORS:后端代码控制,咱们采用的方式

    # cors:    #xss,csrf---跨站请求伪造
    	跨域资源共享:后端技术,就是在响应头中加入 固定的头,就会运行前端访问了
        
    # CORS基本流程
    浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
    浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
    浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错
    
    
    # 什么是简单请求,什么是非简单请求
    	# 符合如下条件,就是简单请求
    	(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
            
    # 演示简单和非简单请求
    	-如果是简单,直接发送真正的请求
        -如果是非简单,先发送options,如果运行,再发真正的
    

    第一种方式---后端添加请求头

    # 前端发送axios不添加请求头---简单请求
      created() {
        this.$axios.get(this.$settings.BASE_URL+ '/home/banner/').then(res=>{
          console.log(res)
        })
      },
        
     # 允许的前端地址
     return APIResponse(data=res.data, headers={
     "Access-Control-Allow-Origin": "http://192.168.1.47:8080"})  # {code:100,msg:成功,data=[{},{}]}
    # 允许所有前端地址
    return APIResponse(data=res.data,headers={'Access-Control-Allow-Origin':'*'})  # {code:100,msg:成功,data=[{},{}]}
    
    

    第二种方式---书写中间件

    解决跨域问题和请求头携带数据

    # 1.重写process_response方法
    from django.utils.deprecation import MiddlewareMixin
    class CorsMiddleWare(MiddlewareMixin):
        def process_response(self, request, response):
            if request.method == 'OPTIONS':  # 解决非简单请求的请求头
                response["Access-Control-Allow-Headers"] = "*"
            # 允许前端的地址,所有请求头允许
            response["Access-Control-Allow-Origin"] = "*"
            return response
        
    # 2. 注册中间件
    MIDDLEWARE = [
        'utils.common_middle.CorsMiddleWare'
    ]
    

    **第三种方式---第三方模块django-cors-headers **

    # 第一步:安装
    	pip install django-cors-headers
    # 第二步:配置app
        INSTALLED_APPS = [
            'corsheaders'
        ]
    
    # 第三步:配置中间件
        MIDDLEWARE = [
            'corsheaders.middleware.CorsMiddleware',
        ]
    # 第四步:在配置文件配置
    # 允许所有域
    CORS_ORIGIN_ALLOW_ALL = True
    # 允许的请求方式
    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',
    	'token',
    )
    
  2. Nginx反向代理 (常用)

  3. JSONP:很老不会用了,它只能发get请求

  4. 搭建Node代理服务器

posted @ 2023-02-19 19:58  魔女宅急便  阅读(49)  评论(0)    收藏  举报
Title