# 浏览器同源策略及跨域问题的解决方案
面试老问这个问题,但是实际开发中却很少遇到这样。开发中有webpack-dev-server
搞定,上线有服务端的大佬帮忙配置好,就算让我前端去搞定我就只会proxy去解决,后端暂时接触的比较少,会使用cors
中间件,别说JSONP是啥玩意,我基本没怎么用过。
参考链接:https://segmentfault.com/a/1190000015597029
# 什么是浏览器同源策略
同源策略(Same origin policy)是一种约定,浏览器最核定的基本安全功能,web是构建在同源策略之上。
同源策略:只允许来自同一站点的资源, 其域名、协议、端口必须相同
# 同源策略又分为以下两种:
# 1.DOM同源策略:禁止对不同的DOM进行操作。这里主要场景就是iframe
跨域的情况,不同域名的iframe
是限制互相访问的 (iframe
内嵌框架)
# 2.XMLHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。
后端:https://my-blogs-kittors.vercel.app/
前端:
URL | 结果 | 原因 |
---|---|---|
https://my-blogs-kittors.vercel.app/ | 成功 | 域名、协议、端口相同 |
http://my-blogs-kittors.vercel.app/ | 失败 | 与服务器的协议不同 |
https://my-blogs-kittors.vercel.app:8080/ | 失败 | 端口不同 |
https://my-blogs-kittors.vercel.com | 失败 | 域名不同 |
# 为啥要有跨域的限制:
主要是为了用户的上网安全
# 如果没有DOM同源策略,也就是说不同域的iframe
之间可以相互访问:
# 1.做个假网站,里面使用iframe
嵌套 一个银行http://mybank.com。
# 2.把iframe
宽高啥的调整到页面全部,这样用户进行除了域名,别的部分和银行的网站没有差别。
# 3.这时如果用户输入账号密码,我们的主网站可以跨域访问到http://mybank.com的dom
节点,就可以拿到用户的密码和账户
# 如果XHRHttpRequest
同源策略,那么黑客可以进行CSRF(跨域请求伪造 Cross-site request forgery)攻击:
# 1.用户登录了自己的银行网页http://mybank.com,http://mybank.com向用户的cookie中添加用户标识。
# 2.用户浏览了恶意页面http://evil.com ,执行页面中的恶意AJAX请求代码。
# 3.http://evil,.com向http://mybank.com 发起AJAX HTTP请求,请求默认把http://mybank.com 对应cookie也同时发送过去
# 4.银行页面可以从发送的cookie中提取用户标识,验证用户无误,response中返回数据,此时数据就泄露了。
# 5.而且由于Ajax在后台执行,用户无法感知这一过程
因此,就有了浏览器同源策略 我们才可以安全上网
# 如何解决跨域问题
# CORS中间件的使用(CORS跨域资源共享 ) 可以接触到服务器的时候
CORS是一种W3C标准,全称是”跨域资源共享“(Cross-origin resource sharing)
这里引入上面链接的文章说明了一些简单请求和非简单请求,
浏览器将CORS请求分为两大类:简单请求(simple request) 和非简单请求(not-so-simple request)。
只要同时满足以下两个条件,就属于简单请求。
(1)请求方法试一下的三种方法之一:
- HEAD
- GET
- POST
(2)HTTP的头信息不能超出以下几种字段
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
1.简单请求
后端:
// 处理成功失败返回格式的工具
const {successBody} = require('../utli')
class CrossDomain {
static async cors (ctx) {
const query = ctx.request.query
// *时cookie不会在http请求中带上
ctx.set('Access-Control-Allow-Origin', '*')
ctx.cookies.set('tokenId', '2')
ctx.body = successBody({msg: query.msg}, 'success')
}
}
module.exports = CrossDomain
# express服务器的解决方法:
这边用的Node.js的express组件的cors
中间件实现
代码配置如下:
// 加载Express模块
const express = require("express");
const server = express();
// 加载CORS模块
const cors = require("cors");
// 使用CORS中间件 解决跨域的问题
server.use(
cors({
origin: ['http://localhost:8085',"http://127.0.0.1:8080", "http://localhost:8080","*"],
})
);