解决跨域问题的 5 种办法

本文节选自我的博客:解决跨域问题的 5 种办法

  • 作者简介:大家好,我是MilesChen,偏前端的全栈开发者。
  • CSDN主页:爱吃糖的猫
  • 我的博客:爱吃糖的猫
  • Github主页: MilesChen
  • 支持我:点赞+收藏⭐️+留言
  • 介绍:The mixture of WEB+DeepLearning+Iot+anything

前言

跨域问题一直是前后端交互过程中遇见频率最高的问题,本文带来五种解决跨域问题的办法,总有一种适合你。

跨域

什么是跨域?

  • 同源:两个资源的 协议、域名、端口都相同。否则就是跨域

为什么要有跨域?

  • 浏览器的安全限制,为了防止读取非同源的DOM、Cookie、LocalStorage、IndexDB;

跨域请求的过程?

  • 向非同源发起请求,请求资源跨域时,浏览器一般会先发起预检请求,检测资源是否支持跨域,再发起真实请求,请求类型为 preflight ,请求方法为OPTIONS 表示预检请求。

解决跨域的五种方式

  1. 把协议、域名、端口改成相同的;
  2. 在响应头添加 Access-Control-Allow-Origin 相关字段来允许跨域,利用这种解决思路具体的实现的方式有 nginx配置、后端手动修改字段CORS、后端中间件请求拦截、谷歌插件等方式;
  3. JSONP,利用了script标签不受浏览器同源策略的影响;
  4. 反向代理,利用跨域只对浏览器有效,在node中开启跨域代理,负责请求转发。Vue和React都有代码配置,适用于开发环境;
  5. CSP(content-Security-policy)设置白名单。

下面来展开聊其中的几个具体实现

Nginx配置解决跨域问题

在nginx服务器中配置,为响应头添加跨域字段

location ^~ /api/ {
    add_header 'Access-Control-Allow-Origin' $http_origin; # 任何域名都支持跨域
    add_header 'Access-Control-Allow-Credentials' 'true';  # 允许前端带上cookie
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers '*';
    if ($request_method = 'OPTIONS') { # 如果是预检请求也要支持跨域
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Origin' $http_orig  in;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
    }
}

JSONP解决跨域问题

JSONP利用了script标签不受浏览器同源策略的影响,可以通过src属性,请求非同源的js脚本。除了script标签,img、link标签也支持跨域。但是img只能跨域图片(其实也可以获取图片二进制再使用JS解析也能拿到数据,但没必要怎么做)、link只能跨域css。

JSONP的4大缺陷:

  1. 只支持get请求
  2. 不安全
  3. 有缓存
  4. 传递信息有限制

JSONP伪代码

其实就是本地定义一个函数,用发起请求(发起的JS脚本请求)的方式调用自己
前端HTML的代码



同级目录JS文件夹下的getdata.js 文件

abc({ name: 'ls', age: 30 })  //回调了HTML中的abc函数

实现JSONP

前端部分




    
    
    Document


    


Node后端部分

const http = require('http')
const url = require('url')
const server = http.createServer()
server.on('request',function(req,res){
    // 将api/test?callback=func 解析为 query和pathname urlobj是个对象还有一起其他内容
    let urlobj = url.parse(req.url,true)
    console.log(urlobj);
    if(urlobj.pathname === '/api/test'){
        // 返回了一个函数 func({name:'mileschen'})
        res.end(`${urlobj.query.callback}(${JSON.stringify({name:'mileschen'})})`)
    }else{
        res.end('404')
    }
})
server.listen(4433,function(){
    console.log('server start');
})

jQuery发起JSONP请求

jQuery是通过动态创建和移除script标签的方式来发起JSONP请求。在发起SONP请求的时候,动态向

中append一个

你可能感兴趣的:(前端,前端,跨域)