Ajax跨域请求_cors

cors

内容回顾:
restful 规范
10个

  1. 除了 jsonp(它只可以发 get 请求), 还有cors(可以发任何请求)。
    解决跨域一般方法:加响应头

  2. VUE + rest framework 示例

    • 登录
    • 课程列表
      • 课程详细
  3. django 里面的content-type:

    • django 的组件,帮我们做跨表的操作。

今日内容

1. 跨域

  • 浏览器的同源策略导致跨域。

浏览器的同源策略:浏览器会将请求拦截,对 ajax 请求进行阻拦。对 href,src属性都不阻拦。
ps:
小公司:静态文件服务器:js,cs 之类的静态都放在里面。
大公司:CDN

解决方案:
      - 客户端浏览器
      - 请求的是 pythondv
      - 发送的请求是 $.ajax(pythonav)
  -------------------------------------
      - 政府站点 pythondv
  -------------------------------------
      - 我的站点 pythonav
  
  这个解决方案:
    第一种:修改 pythondv 网站的请求方式,改成 script
    第二种:政府站点请求方式不用修改,在 pythonav 拿到数据返回的时候,加上响应头。
    
    
  一般就是你返回响应头,客户端给你传 cookie。

2. 解决跨域请求的两种方式

  • jsonp
  • cors

3. 关于 jsonp

https://www.jianshu.com/p/9b01fccf66b7

4. 关于 cors 跨域

随着技术的发展,现在的浏览器可以主动支持设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

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

4.1 简单请求和复杂请求

条件:
    1、请求方式:HEAD、GET、POST
    2、请求头信息:
        Accept
        Accept-Language
        Content-Language
        Last-Event-ID
        Content-Type 对应的值是以下三个中的任意一个
                                application/x-www-form-urlencoded
                                multipart/form-data
                                text/plain
 
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求

4.2 两者的区别

  • 简单请求: 一次请求
  • 非简单请求: 两次请求,在发送数据之前会先发一次请求做'预检',只有'预检'通过后,才会再次发送一次请求用于数据传输。
    4.3 关于预检
- 请求方式:OPTIONS *****
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
     > 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
        Access-Control-Request-Method
     > 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
        Access-Control-Request-Headers

4.4 关于 cors 的优缺点

  • 优点: 可以发送任意请求,而 jsonp 只可以发送 get 请求。
  • 缺点: 当前请求如果是复杂请求的时候得先做个预检,再发真实的请求。发送两次请求可能会有性能上的损耗。

5. jsonp 和 cors 的区别。

JSONP:服务端不用修改,需要改前端。发jsonp请求

JSONP:只能发GET请求

CORS:前端的代码不用修改,服务端的代码需要修改。如果是简单请求的话在服务端加上一个响应头。

CORS:可以发任意请求

6. 基于 cors 实现 ajax 请求

6.1 支持跨域,简单请求。

服务器设置响应头: Access-Control-Allow-Origin = '域名' 或 '*'
 
 
 
     
     
     
     Title
 
 

welcome

from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.views import APIView 
# Create your views here.
class IndexView(APIView):
    def get(self,request,*args,**kwargs):
        ret = {
            'code': 100,
            'data': '777'
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

6.2 支持跨域,复杂请求。

  • 如果是复杂请求在你真正的发请求之前,会先偷偷的发一个OPTION请求,先预检一下,我允许你来你才来。如果要想预检通过,就需要写个 option 请求。
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
  • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
  • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
  • “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age



    
    
    
    Title








from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from rest_framework.views import APIView

class UserIndex(APIView):
    def get(self,request,*args,**kwargs):
        ret = {
            'code': 100,
            'data': 'ppp'
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

    def post(self,request,*args,**kwargs):
        print(request.POST.get('k1'))
        ret = {
            'code':101,
            'data':'fffff',
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

    def options(self, request, *args, **kwargs):
        # self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        # self.set_header('Access-Control-Allow-Headers', "k1,k2")
        # self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        # self.set_header('Access-Control-Max-Age', 10)
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Headers'] = 'h1'
        # response['Access-Control-Allow-Methods'] = 'PUT'
        return response

6.3 跨域获取响应头

  • 默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要再服务器端设置Access-Control-Expose-Headers。



    
    



    

class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('xxoo', "seven")
        self.set_header('bili', "daobidao")
        self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)

6.4 跨域获取 cookie

  • 在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。

如果想要发送:

  • 浏览器端:XMLHttpRequest的withCredentials为true
  • 服务器端:Access-Control-Allow-Credentials为true
  • 注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 *



    
    



    

class MainHandler(tornado.web.RequestHandler):
    
    def put(self):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Credentials', "true")
        self.set_header('xxoo', "seven")
        self.set_header('bili', "daobidao")
        self.set_header('Access-Control-Expose-Headers', "xxoo,bili")
        self.set_cookie('kkkkk', 'vvvvv');
        self.write('{"status": true, "data": "seven"}')

    def options(self, *args, **kwargs):
        self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        self.set_header('Access-Control-Allow-Headers', "k1,k2")
        self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        self.set_header('Access-Control-Max-Age', 10)

你可能感兴趣的:(Ajax跨域请求_cors)