• 前后端通信中的“跨域”解决方案


    跨域解决方案

    协议、域名、端口号,只要有一个不一样都是跨域请求
    
    1、跨域存在的原因
    + 服务器分开部署:WEB服务器、数据服务器、图片服务器…(分开部署,有助于服务器资源的合理利用)
    + 本地开发:本地预览项目 调取 测试服务器上的数据
    + 调取第三方平台API接口
    
    2、跨域主要解决方案
    只对一下三种做了讲解
    + JSONP
    + CORS
    + Proxy
    
    (1)JSONP
    JSONP:利用SCRIPT标签不存在域的限制实现跨域请求
    (1)弊端:
        (A)只能是GET请求 
        (B)不安全,只要服务器支持,谁都可以调用)
    (2)callback必须是一个全局上下文中的函数(防止不是全局的函数,需要把这个函数放置到全局上)
    
    // 前端代码
    function request(url = "", callback) {
      let script;
      // 把传递的回调函数挂载到全局上
      let name = `jsonp${new Date().getTime()}`
      window[name] = (data) => {
        // data 从服务器获取到了结果
        document.body.removeChild(script);
        delete window[name];
        callback && callback(data);
      }
      // 处理URL
      url += `${url.includes('?') ? '&' : '?'}callback=${name}`
      // 发送请求
      script = document.createElement('script')
      script.src = url
      document.body.appendChild(script);
    }
    
    request('http://127.0.0.1:8099/list', result => {
      console.log(result);
    });
    
    // 服务器代码
    let http = require('http')
    let fs = require('fs')
    let url = require('url')
    // 起服务
    let server = http.createServer((req, res)=>{
        let { pathname, query } = url.parse(req.url)
        let callback = query.split('=')[1]
        // 请求
        if(pathname == '/list'){
            // 准备返回的数据
            let result = {
                code: 0,
                data: [10, 20]
            };
            let str = `${callback}(${JSON.stringify(result)})`;
            res.end(str);
        }
    })
    server.listen(8099,()=>{
        console.log('8099接口请求成功')
    })
    
    (2)CORS
    客户端正常请求,服务端设置可请求的 源
    'Access-Control-Allow-Origin':
    (1)*:允许所有源
        不安全;
        不能携带资源凭证;
    (2)设置单一源
        安全;
        可以携带资源凭证( 只能是单一一个源);
    (3)动态设置多个源
        设置一个白名单,客户端请求的源在白名单中,我们把Allow-Origin动态设置为当前这个源
    
    // 前端
    get.onclick = function () {
        fetch('http://127.0.0.1:8099/list', {
          credentials: 'include',
        }).then(res => res.text()).then(data => {
          console.log(data)
        })
    }
    
    // 后端
    let http = require('http')
    let fs = require('fs')
    let url = require('url')
    //白名单
    let allowOrigin = [
        'http://127.0.0.1:8099',
        'http://127.0.0.1:5500',
        'http://127.0.0.1:5502'
    ]
    let server = http.createServer((req, res) => {
        // 设置允许源
        // * : 允许所有源(不安全/不能携带资源凭证)
        // 设置单一源(安全/也可以携带资源凭证/只能是单一一个源)
        // 可以动态设置多个源:每一次请求都会走这个中间件,我们首先设置一个白名单,如果当前客户端请求的源在白名单中,我们把Allow-Origin动态设置为当前这个源
    
        // 前端请求域名
        if (allowOrigin.includes(req.headers.origin)) {
            res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
            res.setHeader('access-control-allow-credentials', true)
        }
        // 后端设置cookie
        res.setHeader('Set-Cookie', ['a=123;SameSite=Secure'])
        let { pathname } = url.parse(req.url)
        
    	// 试探请求:在CORS跨域请求中,首先浏览器会自己发送一个试探请求,验证是否可以和服务器跨域通信,服务器返回200,则浏览器继续发送真实的请求
    	req.method === 'OPTIONS' ? res.send('CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS!') : next();
        
        // 请求
        if (pathname == '/list') {
            // 准备返回的数据
            let result = {
                code: 0,
                data: [10, 20]
            };
            res.end(JSON.stringify(result));
        }
    })
    server.listen(8099, () => {
        console.log('8099接口请求成功')
    })
    
    (3)Proxy
    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
        mode: 'production',
        entry: './src/main.js',
        output: {
            filename: 'main.[hash].min.js',
            path: path.resolve(__dirname, 'build')
        },
        devServer: {
            port: '3000',
            compress: true,
            open: true,
            hot: true,
            proxy: {
                '/': {
                    target: 'http://127.0.0.1:3001',
                    changeOrigin: true
                }
            }
        },
        // 配置WEBPACK的插件
        plugins: [
            new HtmlWebpackPlugin({
                template: `./public/index.html`,
                filename: `index.html`
            })
        ]
    }
    
  • 相关阅读:
    线程执行器(一)
    修改锁的公平性
    Spark学习视频整合
    使用读写锁实现同步数据访问
    使用锁实现同步
    使用工厂类创建线程
    线程的分组
    android手机状态解释,比方android.os.Build.VERSION.SDK
    Android-Dalvik指令集
    selenium使用Xpath定位之完整篇
  • 原文地址:https://www.cnblogs.com/nige/p/14509186.html
Copyright © 2020-2023  润新知