前言

定义

浏览器为了保证用户信息安全,防止恶意网站取数据,禁止不同之间js交互。对于浏览器而言,只要协议域名端口其中有一个不同就会触发同源策略,造成跨域,从而限制交互

为什么限制跨域访问

如果一个网页可以随意的访问一个网站资源,就有可能在用户完全不知情的情况下出现安全问题

浏览器出于安全问题,对同源请求放行,对异源请求限制这些限制规则统称为同源策略因为限制造成的开发问题,称之为跨域(异源)问题

标签发出的跨域请求轻微限制,对 AJAX 发出的跨域请求严厉限制

方法

常用方法

跨域资源共享(CORS)

CORS(Cross-Origin Resource Sharing跨域资源共享定义了必须在访问跨域资源时,浏览器服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部浏览器服务器进行沟通,从而决定请求响应应该成功还是失败

一套机制用于浏览器校验请求。只要服务器明确表示允许,则校验通过服务器明确拒绝没有表示,则校验通过。CORS将请求分为两类,简单请求预检请求:

简单请求
  1. 请求方法为GET、HEAD、POST

  1. 头部字段满足CORS安全规范

  1. 请求头的Content-Typetext/plainmultipart/formdataapplication/xwwwformurlencoded

  1. 服务器响应头,要么同源要么放行

预检请求
浏览器发送预请求
  1. 从哪个源发送的请求:Origin:http://my.com

  1. 请求方式:Access-Controt-Request-Method:POST

  1. 请求改变了哪些请求头:Access-Controt-Request-Headers:contenttype

服务器进行响应
  1. Access-Controt-Allow-Origin:http://my.com…,允许的源,可以多个

  1. Access-Controt-Allow-Method:POST,GET…,允许的方式可以多个

  1. Access-Controt-Allow-Headers:contenttype…,允许改变的请求头,可以多个

  1. Access-Controt-Max-Age:86400,多少秒不用再次检验

jsonp

前端一个函数服务端调用函数传入参数通过参数获取,根本不是AJAX

// 获取返回结果
function callback(resp){
    console.log(resp);
}

// 向服务端请求js文件
function request(url){
    // 生成一个 script 标签
    const script = document.createElement('script')
    // 标签引用 js 路径为填入路径
    script.src = url
    // 标签解析完成之后删除
    script.onload = function(){
        script.remove()
    }
    // 插入 bodydocument.body.appendChild(script)
}

Nginx代理跨域

差别
方法
  1. 浏览器请求自己服务器 proxy

  1. 代理服务器请求目标服务器 target

  1. 服务器之间没有跨域问题,目标服务器响应代理服务器

  1. 代理服务器返回数据

// 引入const express = require('express')
// 创建服务const app = express()
// 接受对路径 /hero 的 GET 请求
app.get('/hero',async (req,res)=>{
    // 使用 cors 解决代理服务器的跨域
    res.header('assess-control-allow-origin','*')
    // 响应一段测试文本
    res.send('你好,我是代理服务器')
    // 在这里请求目标服务器,然后返回前端
})
// 监听9527端口
app.listen(9527,()=>{
    console.log('服务器已启动');
})

扩展学习

Node中间件代理跨域

Vue项目一般使用方法,就是对代理服务器的一种封装

vue.config.js文件配置
module.export = {
    ...
    devServer: {
        proxy: {
            [ process.env.VUE_APP_BASE_API ]: {
                target: 'http://xxxx',    // 代理跨域目标接口
                ws: true,
                changeOrigin: true,
                pathRewrite: {
                    [ '^' + process.env.VUE_APP_BASE_API ] : ''
                }
            }
        }
    }
Node/Express中配置:
const express = require('express')
const proxy = require('http-proxy-middleware')
const app = express()
app.use('/', proxy({ 
    // 代理跨域目标接口 
    target: 'http:    // xxxx:8080', 
    changeOrigin: true, 
    // 修改响应头信息实现跨域并允许带cookie 
    onProxyRes: function(proxyRes, req, res) { 
        res.header('Access-Control-Allow-Origin', 'http://xxxx')
        res.header('Access-Control-Allow-Credentials', 'true')
    }, 
    // 修改响应信息中的cookie域名 
    cookieDomainRewrite: 'www.domain1.com'     // 可以为false表示修改
})); 
app.listen(3000); 

Websocket

WebSocket是HTML5标准中的一种基于TCP但是区别于HTTP的通信协议,因为是长连接,该协议不实行同源政策。以ws://(非加密)和wss://(加密)作为协议前缀

因为WebSocket请求头信息中有Origin字段表示请求源来自哪个域,服务器可以根据这个字段判断是否允许本次通信

// 创建websocket
var socket = new WebSocket('ws://www.baidu.com');
// 发送消息
socket.send('hello WebSocket');
// 接收消息
socket.onmessage = function(event){
    var data = event.data;
}

postMessage

是HTML5引入一个全新的API:跨文档通信 API(Crossdocument messaging)。 这个API为window对象新增一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源

窗口之间传递消息
// 父窗口发起
window.opener.postMessage("我是来自a页面的","http://b.com")

// 子窗口接收
window.onmessage = function(e){
    e = e || event;
    console.log(e.data);//我是来自a页面的
}
// 子窗口发送
window.opener.postMessage('我是来自b页面的', 'http://a.com');
读取其他窗口LocalStorage
// 父窗口调用方法
var obj = { name: 'Jack' };
// 存入对象
window.parent.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://b.com');
// 读取对象
window.parent.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
    // 判断消息是否来自a窗口
    if (e.origin != 'http://a.com') return;
    // "Jack"
    console.log(JSON.parse(e.data).name);
}

b窗口接收消息获取自己localStorage之后再传递给a窗口

window.onmessage = function(e) {
  // 消息来自自己,不予理会
  if (e.origin !== 'http://b.com') return;
  var payload = JSON.parse(e.data);
  // 判断方法进行操作
  switch (payload.method) {
    case 'set':
      localStorage.setItem(payload.key, JSON.stringify(payload.data));
      break;
    case 'get':
      var parent = window.parent;
      var data = localStorage.getItem(payload.key);
      // 如果是获取获取之后传递给a窗口
      parent.postMessage(data, 'http://a.com');
      break;
    case 'remove':
      localStorage.removeItem(payload.key);
      break;
  }
}

单向跨域

利用浏览器对标签发出的跨域请求轻微限制,进行单方面的跨域请求

原文地址:https://blog.csdn.net/wind_notcare/article/details/129548232

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_31578.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注