zoukankan      html  css  js  c++  java
  • 一次跨域请求出现 OPTIONS 请求的问题及解决方法

    问题背景
    浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域
    在前后端开发过程经常会遇到跨域问题。网上也都有解决方案。


    写这篇文章时,我们碰到的一个场景是:要给s系统做一个扩展,前端的html、js放在s系统里,后端需要做一个单独的站点N.B.com。这就导致了跨域问题,大多数时候 前后端用一个CORS方案 解决跨域问题就可以了。但是我这次有点特别。


    前端这边是一个get请求,按理说也没啥,但是在请求的header里面要添加两个自定义的header

    
      GET http://localhost:8080/api/v1/users
      Accept: */*
      Content-Type: application/json
      Authorization: token:21232f297a57a5a743894a0e4a801fc3
      Username: admin
    
    

    增加了两个自定义字段 Authorization和Username
    在请求时 我看到 network里面出现了两次请求记录 第一次是一个 OPTION请求 状态码200第二次是我的get请求 状态码 401


    可以这边后端已经做了CORS处理。为何还出现这种情况呢。
    我们一般在项目里解决跨域问题简单说会采取方案有

    1. 使用ajax直接跨域访问

    2.使用JsonP。实际使用时,由于JsonP向Server提交URL的长度限制在8000字符,超过了则被浏览器拒绝,因此不采用。

    对于第一种方案,后端需要做的工作是:
    接口允许允许跨域请求:

    
    header('Access-Control-Allow-Origin:*');  //支持全域名访问,不安全,部署后需要限制为R.com
    header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); //支持的http动作
    header('Access-Control-Allow-Headers:x-requested-with,content-type');  //响应头 请按照自己需求添加。
    
    

    前端发起跨域请求:就是正常的$.ajax请求即可。我的项目用的vue全家桶 用的axios 发送的请求

    
    // request拦截器
    service.interceptors.request.use(
      config => {
        if (store.getters.token) {
          config.headers['Authorization'] =`token:${getToken()}` 
          config.headers['Username'] =`getUsername()`
        }
        return config
      },
      error => {
        // Do something with request error
        Promise.reject(error)
      }
    )
    

    但是,碰到个问题,国内网站基本没有讲,就是option请求问题。

    在正式跨域的请求前,浏览器会根据需要,发起一个“PreFlight”(也就是Option请求),用来让服务端返回允许的方法(如get、post),被跨域访问的Origin(来源,或者域),还有是否需要Credentials(认证信息)
    三种场景:

    1. 如果跨域的请求是Simple Request(简单请求 ),则不会触发“PreFlight”。Mozilla对于简单请求的要求是:

    以下三项必须都成立:

    1. 只能是Get、Head、Post方法
    2. 除了浏览器自己在Http头上加的信息(如Connection、User-Agent),开发者只能加这几个:Accept、Accept-Language、Content-Type、。。。。
    3. Content-Type只能取这几个值:

    application/x-www-form-urlencoded
    multipart/form-data
    text/plain

    XHR对象对于HTTP跨域请求有三种:简单请求、Preflighted 请求、Preflighted 认证请求。简单请求不需要发送OPTIONS嗅探请求,但只能按发送简单的GET、HEAD或POST请求,且不能自定义HTTP Headers。Preflighted 请求和认证请求,XHR会首先发送一个OPTIONS嗅探请求,然后XHR会根据OPTIONS请求返回的Access-Control-*等头信息判断是否有对指定站点的访问权限,并最终决定是否发送实际请求信息。
    那么我的get请求呢?
    原来,产生 OPTIOINS 请求的原因是:自定义 Headers 头信息导致的。
    浏览器会去向 Server 端发送一个 OPTIONS 请求,看 Server 返回的 "Access-Control-Allow-Headers" 是否有自定义的 header 字段。因为我之前没有返回自定义的字段,所以,默认是不允许的,造成了客户端没办法拿到数据。

    那么这样 的话如果后端是python的话

    
    rom corsheaders.defaults import default_headers
    
    CORS_ALLOW_HEADERS = default_headers + (
        'Authorization,Username'
    )
    

    前端这边如果用的vue全家桶 可以这样搞一下

    
    module.exports = {
        NODE_ENV: '"development"',
        ENV_CONFIG: '"dev"',
        BASE_API: '"/proxy"'
    }
    

    
          '/proxy': {
            target: 'http://jupiter.dev.grdoc.org/',
            changeOrigin: true,
            pathRewrite: {
              '^/proxy': '/'
            },
            sesure:false
          }
        
    

    开发环境这样搞一下 应该就不算跨域了。


    我是山豆 我的gitHub

  • 相关阅读:
    SQL常用关键字
    SQL 笔记1,left join,group by,having
    SpringIDE的安装
    一些有用的书籍,也许需要看看
    执行力
    Q12问题
    WebCollector Cookbook (WebCollector中文文档):
    SSM配置文件
    wkhtmltopdf Windows下 测试demo 成功
    html2pdf 中文支持问题
  • 原文地址:https://www.cnblogs.com/qixidi/p/10179736.html
Copyright © 2011-2022 走看看