跨域
跨域报错
此报错的关键词: Access-Control-Allow-Origin
为什么会跨域
跨域: 网页中利用JS脚本方式, 请求其他来源中的数据
浏览器自带的同源策略
: 当你在网页中用JS发送请求时, 会自动查看是否同源
-
同源: 协议 + 域名 + 端口号 三者都相同
协议://域名:端口号
比如 http://localhost:3000
协议:http; 域名:localhost; 端口号:3000;
网页的开发方案分两类: -
前后端
不分离
- 早期互联网开发时, 采用 PHP, JAVA 语言. 当年对前端要求不高, 所以服务器人员需要兼任前端开发
- 早期互联网开发时, 采用 PHP, JAVA 语言. 当年对前端要求不高, 所以服务器人员需要兼任前端开发
-
前后端
分离
总结: 当网站被高并发大量访问时 -
前后端不分离: 由服务器完成所有任务, 服务器存在极大的压力
-
前后端分离: 服务器负责查数据库, 浏览器服务器拼接成html; 服务器把拼接HTML的任务分离出去, 自身压力减轻, 更适合当前场景.
CORS
- cors原理: 在服务器上增加一个白名单, 浏览器在发请求时会来服务器询问, 是否允许其他来源的访问. 服务器告知允许即可
app.use(cors())
// node.js 专属的模块化语法
// 功能等价于 web的 脚本引入操作 <script src="xxx.js"></script>
const express = require('express');
const cors = require('cors')
const app = express()
// cors原理: 在服务器上增加一个白名单, 浏览器在发请求时会来服务器询问, 是否允许其他来源的访问. 服务器告知允许即可
// app.use(cors())
// 白名单方案: 指定哪些来源可以访问
app.use(cors({
origin: ['http://localhost:5500', 'http://127.0.0.1:5500']
}))
// 测试方式: 分别使用一下方式访问服务器, 看结果
// http://localhost:5500/public/index.html 在白名单没问题
// http://127.0.0.1:5500/public/index.html 在白名单没问题
// http://127.0.0.1:3000 不是同源,也不在白名单, 报错!
// http://localhost:3000 就是同源的没问题
// 通过浏览器输入 localhost:3000 来访问此服务器
app.listen(3000, () => {
console.log('服务器已开启, 端口3000');
})
// 启动命令分两种方案:
// node app.js
// 每次带有有修改 都需要关闭重开
// nodemon app.js
// 每次有修改,会自动重启
// 新增欢迎页面, 属于静态文件
// 设置 public 目录为 静态文件管理目录, 当访问服务器时, 会从这个目录中查找文件
app.use(express.static('public'))
// 制作数据接口:
// localhost:3000/emps
app.get('/emps', (req, res) => {
var emps = [
{ ename: "mike", age: 18 },
{ ename: "john", age: 38 },
{ ename: "lucy", age: 28 },
]
// 发送给访问接口的人
res.send({ emps })
})
JSONP
app.js
const express = require('express');
const app = express()
app.listen(3000, () => {
console.log('服务器已开启, 端口3000');
})
app.use(express.static('public'))
app.get('/emps', (req, res) => {
// 从GET请求的参数中, 读取 callback 属性的值
const { callback } = req.query
var emps = [
{ ename: "mike", age: 18 },
{ ename: "john", age: 38 },
{ ename: "lucy", age: 28 },
]
// 转为JSON字符串
var emps_str = JSON.stringify(emps)
var resp = callback + `(${emps_str})`
console.log('resp:', resp)
res.send(resp)
})
index.html
// 脚本的src的作用: 从指定的文件中下载所有代码 并执行
// 能够通过 src 来请求接口中的数据呢?
const script = document.createElement('script')
// callback自定义
script.src = 'http://localhost:3000/emps?callback=getEmps'
$('body').append(script) // 添加到body中, 才能执行
function getEmps(data) {
console.log('data:', data)
}
PROXY
app.js
const express = require('express');
const cors = require('cors'); // 跨域模块
const proxy = require('express-http-proxy'); // 代理服务器模块
const app = express()
// 过程: html --请求1--> express服务器 ---请求2--> 斗鱼服务器
// 请求1: 存在跨域问题; 请求2: 无跨域问题, 服务器之间的交互.
app.use(cors()) // 解决 请求1 的跨域问题
app.listen(3000, () => {
console.log('服务器已开启, 端口3000');
})
// localhost:3000/baidu -> 请求到 百度的页面
app.use('/baidu', proxy('http://www.baidu.com'))
// localhost:3000/jd -> 转到 http://jd.com
app.use('/jd', proxy('http://jd.com'))
// localhost:3000/dy
app.use('/dy', proxy('https://m.douyu.com'))
index.html
<script>
// var url = 'https://m.douyu.com/api/room/list?page=1&type=yz'
// 到 express 服务器提供的 http://localhost:3000/dy 中要数据
// express 会代为转发到 https://m.douyu.com 网站
var url = 'http://localhost:3000/dy/api/room/list?page=1&type=yz'
// 问题: 接口存在跨域 但是 服务器无法修改代码
// - 导致 cors 和 jsonp 方案无法使用
$.get(url, data => {
console.log('斗鱼数据:', data);
})
总结
跨域问题
-
什么是跨域?
-
浏览器专有的, 属于一种安全策略.
-
同源策略: 当在网页中利用AJAX 到另一个数据源请求数据时, 默认报错.
同源: 协议 域名 端口号 都必须相同
-
-
如何解决跨域
-
CORS: 推荐. 由服务器独立解决
- 原理: 在服务器上设置白名单. 允许非同源的访问. 采用cors模块
-
JSONP: 服务器+前端 共同解决
- 在前端利用 script 的 src 来发送请求, 因为此方式不存在跨域问题
- 服务器: 需要在回传信息时, 添加回调函数的调用
- 特点: 仅支持GET请求 + 仅支持JSON格式数据的传递
-
PROXY: 代理模式. 仅需要前端解决.
无需修改服务器代码
-
利用 服务器之间的交互没有跨域问题的特征
-
搭建Express服务器作为搭理的角色
-
-
补充:XSS: 跨站脚本攻击
英文名:
Cross Site Script Attack
理论上简写是: CSS, 但是这个名称和 层叠样式表的缩写重名, 所以改为
XSS
我们的网站中, 如果使用了来自其他网站提供的脚本代码 – 是不安全的
做法
如果脚本代码中存在恶意代码, 会导致网站被攻击!!
总结: 不要使用不受信任的网站提供的脚本, 应该从官方下载
最好把脚本下载到本地使用, 而不是使用远程脚本. 有效防止远程脚本变更导致的安全性问题!!