为什么要跨域?

 因为浏览器同源策略(协议、域名端口号)的原因,我们想访问其他服务器上面的资源

 

什么是同源策略?

 

    同源策略,它是Netscape(网景)提出的一个著名的安全策略。所谓同源是指,域名,协议,端口相同

常见域名后缀

  -com 国际的
  -cn 中国
  -uk 英国
  -org 非盈利的组织、团体
  -edu 教育

 

常见的跨域技术

  - jsonp

          - jsonp 缺点:只能解决get请求

           - jsonp 包含两部分:回调函数和数据。

              回调函数:当响应到来时要放在当前页面被调用的函数。 

              数据:就是传入回调函数中的json数据,也就是回调函数的参数了

   原理如下:

    //因为,带有src属性的标签,不受同源策略的约束,我们可以通过动态创建带有src的标签,来访问服务器返回请求数据、结果 

    //当我们通过script标签请求时

    //后台就会根据相应的参数来生成相应的json数据

    //最后这个返回的json数据(代码)就会被放在当前js文件中被执行

    //至此跨域通信完成

<script src="http://localhost:9090/list"></script>

<script>
    function jsonp(url, fn) {
        let cb = "cb";
        window[cb] = fn;
        let script = document.createElement("script");
        script.src = url + "?cb=" + cb;
        document.body.appendChild(script)
    }

    jsonp("http://localhost:9090/list", function (res) {
        console.log(res)
    })
</script>

  - 服务器跨域 cros  

    - CORS:一种跨域访问的机制,可以让AJAX实现跨域访问;CORS允许一个域上的网络应用向另一个域提交跨域AJAX请求。
  
    服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求。就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

    - cros 优点:允许所有请求 跨域 实现资源共享

//在3000端口时,先引用一下axios包

<script>
    axios.get("http://localhost:9090/list").then(res => {
        console.log(res)
    })
   
</script>

//用experss做后端,在9090端口时

app.get("/list", (req, res, next) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    console.log(121)
    res.end("var a=111");
})

  - 代理服务器  

    1.非vue框架(2次跨域)
    利用node+express+http-proxy-middleware搭建一个proxy服务器。

    // 引用依赖
    var express = require('express');
    var proxy = require('http-proxy-middleware');


    // proxy 中间件的选择项
    var options = {
        target: 'http://localhost:8080', // 目标服务器 host
        changeOrigin: true,               // 默认false,是否需要改变原始主机头为目标URL
        ws: true,                         // 是否代理websockets
        router: {
            // 如果请求主机 == 'dev.localhost:3000',

            // 重写目标服务器 'http://www.example.org' 为 'http://localhost:8000'
            'dev.localhost:3000': 'http://localhost:8000'
        }
    };


    // 创建代理
    var exampleProxy = proxy(options);


    // 使用代理
    var app = express();
    app.use('/', exampleProxy);
    app.listen(3000);

    // 将8080代理到3000端口上,所以起3000的端口  

    2.vue框架(1次跨域)
    利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers跨域信息了。

    1)vue-cli 2.9.3版本生成的框架下,在config文件夹下的index.js

    dev:{
        proxyTable: {
            '/api': {
                target: 'http://localhost:3000',   //目标接口域名
                changeOrigin: true,  //是否跨域
                secure: false,  // 如果是https接口,需要配置这个参数
              }
        },
    }

    //接口以/api开头,如:/api/login     

    2)vue-cli 3.0以上版本生成的脚手架下,在自己建立的vue.config.js

    module.exports = {
        devServer: {
            proxy: 'http://localhost:3000'
        }
    }

    3)正向代理,在webpack.dev.conf.js文件中

    before(app){
        app.get("/getList", (req, res) => {
            const url = "http://localhost:3000"
            axios.get(url).then(mock => {
                res.json({
                    code: 1,
                    data: mock.data
                })
            }).catch(err => {
                res.json({
                    code: 0,
                    data: err
                })
            })
        })
    }

    // react,vue,express都可以使用正向代理此方法

    4)普通 node 正向代理,在 server.js 文件中

const https = require('https')
const { createServer } = require('http')

createServer((req, res) => {
    if (req.url == '/api') {
        const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg?-=getUCGI17099600255385994&g_tk=
            5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&
            notice=0&platform=yqq.json&needNewCode=0&data=%7B%22detail%22%3A%7B%
            22module%22%3A%22musicToplist.ToplistInfoServer%22%2C%22method%22%3A%
            22GetDetail%22%2C%22param%22%3A%7B%22topId%22%3A4%2C%22offset%22%3A0%2C%
            22num%22%3A20%2C%22period%22%3A%222019-08-15%22%7D%7D%2C%22comm%22%3A%7B%
            22ct%22%3A24%2C%22cv%22%3A0%7D%7D
' let chunks = '' https.get(url, result => { result.on('data', chunk => { chunks += chunk }) result.on('end', () => { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }) res.end(chunks) }) }) } }).listen(8080, () => { console.log('server is running at 8080') }) // 在 index.html 文件中 // fetch('http://localhost:8080/api').then(res => res.json()).then(res => { // console.log(res) // })

   3.react框架

    在package.json中加上proxy代理配置

"proxy": "http://localhost:9090"

    // 如果不成功就,设置全局进程的端口号 set PORT=9090

    //node 环境 --->process.env.PORT

    //console.log(process.env.PORT)

  为什么react 可以在package.json中一句话就可以解决跨域,而vue要写很多?

     这个特性可以在react-scripts@2.3及更高的版本使用,所以react中多了一个react-scripts包

附:

  什么是正向代理?

    正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。为了从原始服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转交并且将获得的内容返回给客户端。

    正向代理的情况下客户端必须要进行一些特别的设置才能使用。

  正向代理的优点和用途:

    (1)访问原来无法访问的资源,如google

    (2) 可以做缓存,加速访问资源

    (3)对客户端访问授权,上网进行认证

    (4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

  什么是反向代理?

    反向代理是代理服务器的一种。服务器根据客户端的请求,从其关联的一组或多组后端服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器簇的存在。

  反向代理的优点和用途:

    (1)提高了内部服务器的安全

    (2)加快了对内部服务器的访问速度

    (3)节约了有限的IP资源

  正向代理和反向代理的区别:

    位置不同 :

        正向代理,架设在客户端和目标服务器之间; 
        反向代理,架设在服务器端;

    代理对象不同 :
        正向代理,作为客户端的代理,将从互联网上获取的资源返回给一个或多个的客户端,服务端(如Web服务器)只知道代理的IP地址而不知道客户端的IP地址,客户端借由正向代理可以间接访问很多不同互联网服务器(簇)的资源。
        反向代理,是作为服务器端(如Web服务器)的代理使用,而不是客户端。反向代理是供很多客户端都通过它间接访问不同后端服务器上的资源,而不需要知道这些后端服务器的存在,而以为所有资源都来自于这个反向代理服务器。

    用途不同 :
        正向代理,为在防火墙内的局域网客户端提供访问Internet的途径; 
        反向代理,将防火墙后面的服务器提供给Internet访问;

    安全性不同 :
        正向代理,允许客户端通过它访问任意网站并且隐藏客户端自身,因此必须采取安全措施以确保仅为授权的客户端提供服务; 
        反向代理,都对外都是透明的,访问者并不知道自己访问的是哪一个代理。

 

posted on 2019-07-25 11:29  Ann&  阅读(529)  评论(1编辑  收藏  举报