在javascript中,同源策略是什么,解决跨域问题

同源策略(Same-Origin Policy,SOP)是一种浏览器安全机制,用于限制来自不同源(不同域名、协议或端口)的网页之间的交互。它是为了保护用户的隐私和安全而设计的。

同源策略的原理是,当一个网页加载了来自其他源的脚本、图像、样式表或其他资源时,浏览器会检查这些资源的来源是否与加载当前网页的源相同。如果不同源,浏览器会禁止网页对这些资源的访问。

同源策略的存在是为了防止恶意网页获取用户敏感信息或利用用户的身份执行恶意操作。如果没有同源策略,恶意网页可能通过加载第三方脚本或资源,窃取用户的登录凭证、个人信息,或者篡改用户的数据。

如果没有同源策略,浏览器会变得不安全,可能导致以下问题:

跨站脚本攻击(Cross-Site Scripting,XSS):恶意网页可以插入脚本来获取用户的敏感信息,如用户名、密码。
跨站请求伪造(Cross-Site Request Forgery,CSRF):恶意网页可以伪造用户的请求,以用户的身份执行未经授权的操作。
跨域数据泄漏:恶意网页可以通过其他源加载资源,获取用户的浏览历史、Cookie、个人资料等信息。

同源策略通过限制跨源访问来保护用户数据的安全,使得一个网页只能与同一源的其他网页进行数据交互。要在浏览器允许不同源之间的通信,可以使用 Cross-Origin Resource Sharing(CORS)机制来明确授权。这样,可以在一定程度上实现安全的跨域通信。

总的来说,同源策略是为了保护用户的隐私和安全,防止恶意网页对用户数据进行操纵和窃取。

什么是同源策略?

  1. 一个域下的js脚本未经允许的情况下,不能访问另一个域名下的内容。
  2. 通常判断跨域的依据是协议,域名,端口号是否相同,不同则跨域。
  3. 同源策略是对js脚本的一种限制,并不是对浏览器的限制,像img,script脚本请求不会有限制。
  4. 同源策略是一种安全协议
  5. 比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。
    如果缺少了同源策略,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源(例如switch host切域名)

方案1: jsonp 跨域

访问脚本链接后,这个脚本文件内容是,后台返回函数调用,且它的参数是后台给的数据,但是这个函数确是前端定义的,当前端执行了饭回的js文件内容,就是执行该函数,这样前端就拿到了后台传的数据。

function jsonp(url, params, callback) {
  const callbackName = "jsonp_" + Date.now();
  const queryString = Object.keys(params)
    .map(
      (key) => encodeURIComponent(key) + "=" + encodeURIComponent(params[key])
    )
    .join("&");
  const script = document.createElement("script");
  script.src = url + "?" + queryString + "&callback=" + callbackName;
  window[callbackName] = function (data) {
    callback(data);
    document.head.removeChild(script);
    delete window[callbackName];
  };
  document.head.appendChild(script);
}
jsonp("http://www.example.com/api", { user: "admin" }, function (data) {
  console.log(data);
});

方案2: document.domain +iframe跨域

两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。

1.)父窗口:(http://www.domain.com/a.html)

<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin'; 设置数据
</script>

2.)子窗口:(http://child.domain.com/b.html)

document.domain = 'domain.com';
// 获取父窗口中的变量
alert(window.parent.user);  获取数据

方案3:nginx代理跨域

通过 Nginx 配置反向代理,将跨域请求转发到同源接口,从而避免浏览器的同源策略限制。

下面是一个示例配置,展示了如何通过 Nginx 实现跨域代理:

server {
  listen 80;
  server_name your-domain.com;

  location /api {
    # 设置代理目标地址
    proxy_pass http://api.example.com;
    
    # 设置允许的跨域请求头
    add_header Access-Control-Allow-Origin $http_origin;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Credentials true;
    add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
    
    # 处理预检请求(OPTIONS 请求)
    if ($request_method = OPTIONS) {
      return 200;
    }
  }
}

在上面的示例中,假设你的域名是 your-domain.com,需要代理访问 api.example.com。你可以将这个配置添加到 Nginx 的配置文件中。

这个配置会将 /api 路径下的请求代理到 http://api.example.com。同时,通过添加 Access-Control-Allow-* 头部,允许跨域请求的来源、方法、头部等。

这样,当你在前端发送请求到 /api 路径时,Nginx 会将请求代理到 http://api.example.com,并在响应中添加跨域相关的头部,从而解决跨域问题。注意要根据实际情况进行配置,包括监听的端口、域名和代理的目标地址等。

方案4:nodejs中间件代理跨域

使用 Node.js 构建一个中间件,在服务器端代理请求,将跨域请求转发到同源接口,然后将响应返回给前端。

可以使用 http-proxy-middleware 模块来创建一个简单的代理服务器。下面是一个示例代码:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');

const app = express();

// 创建代理中间件
const apiProxy = createProxyMiddleware('/api', {
  target: 'http://api.example.com', // 设置代理目标地址
  changeOrigin: true, // 修改请求头中的 Origin 为目标地址
  pathRewrite: {
    '^/api': '', // 重写请求路径,去掉 '/api' 前缀
  },
  // 可选的其他配置项...
});

// 将代理中间件应用到 '/api' 路径
app.use('/api', apiProxy);

// 启动服务器
app.listen(3000, () => {
  console.log('Proxy server is running on port 3000');
});

在上面的示例中,首先使用 express 框架创建一个服务器实例。然后,使用 http-proxy-middleware 模块创建一个代理中间件。通过配置代理中间件的 target 选项,将请求代理到目标地址 http://api.example.com

你可以通过其他可选的配置项来进行更多的定制,例如修改请求头、重写请求路径等。在这个示例中,我们将代理中间件应用到路径 /api 下,即当请求路径以 /api 开头时,会被代理到目标地址。

最后,启动服务器并监听指定的端口(这里是 3000)。

请确保你已经安装了 express 和 http-proxy-middleware 模块,并将上述代码保存为一个文件(例如 proxy-server.js)。然后通过运行 node proxy-server.js 来启动代理服务器。

现在,当你在前端发送请求到 /api 路径时,Node.js 代理服务器会将请求转发到 http://api.example.com,从而实现跨域访问。记得根据实际情况修改目标地址和端口号。

方案5:后端在头部信息里面设置安全域名

后端可以在响应的头部信息中设置 Access-Control-Allow-Origin 字段,指定允许跨域访问的域名。例如,在 Node.js 中可以使用 cors 模块来实现:

const express = require('express');
const cors = require('cors');
const app = express();
// 允许所有域名跨域访问
app.use(cors());
// 其他路由和逻辑处理...
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

方案6: 通过webpack devserver代理

使用 webpack-dev-server 的代理功能可以实现在开发过程中的跨域请求。你可以配置 devServer 对象中的 proxy 选项来设置代理。下面是一个示例配置:

module.exports = {
  // 其他配置项...
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.example.com', // 设置代理目标地址
        pathRewrite: { '^/api': '' }, // 重写请求路径,去掉 '/api' 前缀
        changeOrigin: true, // 修改请求头中的 Origin 为目标地址
      },
    },
  },
};

在上面的示例中,我们配置了一个代理,将以 /api 开头的请求转发到 http://api.example.com。通过 pathRewrite 选项,我们去掉了请求路径中的 /api 前缀,以符合目标地址的接口路径。

将上述配置添加到你的 webpack.config.js 文件中,然后启动 webpack-dev-server。现在,当你在前端发送以 /api 开头的请求时,webpack-dev-server 会将请求转发到目标地址,并返回响应结果。

注意,这里的配置是针对开发环境下的代理,当你构建生产环境的代码时,代理配置不会生效。

请确保你已经安装了 webpack-dev-server,并在你的 package.json 文件的 scripts 中添加启动命令,例如:

{
  "scripts": {
    "start": "webpack-dev-server --open"
  }
}

运行 npm start 或 yarn start 来启动 webpack-dev-server

这样,通过配置 webpack-dev-server 的代理,你就可以在开发过程中实现跨域请求。记得根据实际情况修改目标地址和请求路径。

方案7: CORS(跨域资源共享)

在服务端设置响应头部,允许特定的域名或所有域名访问该资源。可以通过在响应头部中设置 Access-Control-Allow-Origin 字段来指定允许访问的域名。

示例代码(Node.js + Express):

const express = require('express');
const app = express();

// 允许所有域名访问
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  next();
});

// 路由和处理逻辑
// ...

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

方案8: WebSocket

使用 WebSocket 协议进行通信,WebSocket 不受同源策略限制,因此可以在不同域之间进行双向通信。

示例代码(JavaScript):

const socket = new WebSocket('ws://example.com/socket');

socket.onopen = () => {
  console.log('WebSocket connection established.');
  // 发送数据
  socket.send('Hello, server!');
};

socket.onmessage = (event) => {
  console.log('Received message from server:', event.data);
};

socket.onclose = () => {
  console.log('WebSocket connection closed.');
};

方案9: 代理服务器

在同一域名下,前端通过发送请求给同域下的代理服务器,然后由代理服务器转发请求到目标服务器,并将响应返回给前端,实现跨域请求。

示例代码(Node.js + Express):

const express = require('express');
const axios = require('axios');
const app = express();

app.get('/api/data', (req, res) => {
  // 向目标服务器发送请求
  axios.get('http://api.example.com/data')
    .then((response) => {
      // 将目标服务器的响应返回给前端
      res.json(response.data);
    })
    .catch((error) => {
      res.status(500).json({ error: 'An error occurred' });
    });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值