义乌免费做网站,优秀网页设计代码,wordpress中文cms主题模板下载,郑州企业网站快速优化价格跨域 想要了解跨域#xff0c;首要要了解源 什么是源#xff0c;源等于协议加域名加端口号 只有这三个都相同#xff0c;才是同源#xff0c;反之则是非同源。 比如下面这四个里#xff0c;只有第4个是同源 而浏览器给服务器发送请求时#xff0c;他们的源一样#xff0… 跨域 想要了解跨域首要要了解源 什么是源源等于协议加域名加端口号 只有这三个都相同才是同源反之则是非同源。 比如下面这四个里只有第4个是同源 而浏览器给服务器发送请求时他们的源一样就是同源请求反之就是非同源请求非同源请求又称为跨域。 当你是跨域时浏览器为了确保资源安全会对跨域的访问资源做出一些限制也就是浏览器的同源策略。 这是W3C上对同源策略的说明https://www.w3.org/Security/wiki/Same_Origin_Policy 浏览器会对跨域做出哪些限制 例如源a和源b它们是非同源的则浏览器会有如下限制 1. DOM访问限制源a的脚本不能读取和操作源b的DOM。 页面1 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. h1我是页面1/h1
10. button onclickshowDOM()获取页面2的DOM/button
11. br
12. iframe idframePage src./demo.html/iframe
13. !-- iframe idframePage srchttps://www.baidu.com/iframe --
14.
15. script typetext/javascript
16. function showDOM(){
17. const framePage document.getElementById(framePage)
18. console.log(framePage.contentWindow.document.body) //同源的可以获取非同源的无法获取
19. }
20. /script
21. /body
22. /html页面2 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. h2我是页面2/h2
10. /body
11. /html页面是这样的 点击获取 换一个不同源的页面 1. body
2. h1我是页面1/h1
3. button onclickshowDOM()获取页面2的DOM/button
4. br
5. !-- iframe idframePage src./demo.html/iframe --
6. iframe idframePage srchttps://www.bilibili.com/iframe
7.
8. script typetext/javascript
9. function showDOM() {
10. const framePage document.getElementById(framePage)
11. console.log(framePage.contentWindow.document.body) //同源的可以获取非同源的无法获取
12. }
13. /script
14. /body获取DOM 获取不到 2. 第二个限制源a不能访问源b的cookie 3. !DOCTYPE html
4. html langen
5.
6. head
7. meta charsetUTF-8
8. meta nameviewport contentwidthdevice-width, initial-scale1.0
9. titleDocument/title
10. /head
11.
12. body
13. h1我是页面1/h1
14. button onclickgetCookie()获取页面2的cookie/button
15. br
16. !-- iframe idframePage src./demo.html/iframe --
17. iframe idframePage srchttps://www.bilibili.com/iframe
18.
19. script typetext/javascript
20. function getCookie() {
21. const framePage document.getElementById(framePage)
22. console.log(framePage.contentWindow.document.cookie) //同源的可以获取非同源的无法获取
23. }
24. /script
25. /body
26.
27. /html还是一样的页面这次获取的是cookie 也是获取不到的因为你在获取document这一步就已经失败了 3. ajax响应数据限制源a可以给源b发请求但是无法获取源b响应的数据。 这是一个获取头条新闻的页面 代码 28. !DOCTYPE html
29. html langen
30. head
31. meta charsetUTF-8
32. meta nameviewport contentwidthdevice-width, initial-scale1.0
33. titleDocument/title
34. /head
35. body
36. button onclickgetNews()获取头条新闻/button
37.
38. script
39. async function getNews() {
40. const result await fetch(https://www.toutiao.com/hot-event/hot-board/?origintoutiao_pc);
41. const data await result.json();
42. console.log(data);
43. }
44. /script
45. /body
46. /html页面 获取不到 备注在上述限制中浏览器对 Ajax 获取数据的限制是影响最大的一个且实际开发中经常遇到。 几个注意点 跨域限制仅存在浏览器端服务端不存在跨域。即使跨域了ajax请求也可以正常发出但响应数据不会交给开发者。linkscriptimg这些标签发出的请求也可能跨域只不过浏览器对标签跨域不做严格限制对开发几乎无影响。 那么要如何解决跨域 想要解决跨域一般有三种方法 第一种用CORS解决ajax跨域问题 CORS 概述 CORS 全称Cross-Origin Resource Sharing跨域资源共享是用于控制浏览器校验跨域请求的一套规范服务器依照 CORS 规范添加特定响应头来控制浏览器校验大致规则如下 服务器明确表示拒绝跨域请求或没有表示则浏览器校验不通过。服务器明确表示允许跨域请求则浏览器校验通过。 了解了CORS之后还要了解一下简单请求和复杂请求 CORS 会把请求分为两类分别是1.简单请求、2.复杂请求。 简单请求要满足这个三个条件 请求方法要为 get, head或者post。请求头字段要符合CORS安全规范(https://fetch.spec.whatwg.org/#cors-safelisted-request-header), 一般只要不手动修改请求头都能符合改规范。请求头的Content-Type的值只能是这三种: text/plain multipart/form-data application/x-www-form-urlencoded 不满足这三个要求的请求都是复杂请求而复杂请求会自动发送预检请求。 预检请求是一种在实际跨域请求发出之前由浏览器自动发出的一种请求。主要用于向服务器确认是否允许接下来的跨域请求。基本流程是这样的浏览器先发起一个options请求携带这个几个请求头Origin发起请求的源Access-Control-Request-Method实际请求的HTTP方法Access-Control-Request-Headers实际请求中使用的自定义头。如果通过预检才会继续发起实际的跨域请求。 这就是预检请求 CORS 解决简单请求跨域 前端 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. button onclickgetData()获取数据/button
10.
11. script
12. async function getData() {
13. const url http://127.0.0.1:8081/;
14. const result await fetch(url);
15. const data await result.json();
16. console.log(data);
17. }
18. /script
19. /body
20. /html服务端代码以express框架为例 1. const express require(express);
2. const app express();
3.
4. app.get(/, (req, res) {
5. res.send([{ name: 张三, age: 19 }])
6. })
7.
8. app.listen(8081, () {
9. console.log(服务器成功启动);
10. })这个时候是获取不到数据的 设置下cors 1. const express require(express);
2. const app express();
3.
4. app.get(/, (req, res) {
5. res.setHeader(Access-Control-Allow-Origin,http://127.0.0.1:5500)
6. res.send([{ name: 张三, age: 19 }])
7. })
8.
9. app.listen(8081, () {
10. console.log(服务器成功启动);
11. })这样就能获取到数据了 整体思路服务器在给出响应时通过添加Access-Control-Allow-Origin响应头来明确表达允许某个源发起跨域请求随后浏览器在校验时直接通过。 像这样的设置是允许某个源跨域 1. // 允许 http://127.0.0.1:5500 这个源发起跨域请求
2. res.setHeader(Access-Control-Allow-Origin, http://127.0.0.1:5500)而这样则是允许所有源跨域 1. // 允许所有源发起跨域请求
2. res.setHeader(Access-Control-Allow-Origin, *)CORS 解决复杂请求跨域 第一步服务器先通过浏览器的预检请求服务器需要返回如下响应头 Access-Control-Allow-Origin允许的源 Access-Control-Allow-Methods允许的方法 Access-Control-Allow-Headers允许的自定义头 Access-Control-Max-Age预检请求的结果缓存时间可选 第二步处理实际的跨域请求与处理简单请求跨域的方式相同 服务器代码 1. const express require(express);
2. const app express();
3.
4. app.options(/, (req, res) {
5. res.setHeader(Access-Control-Allow-Origin, http://127.0.0.1:5500)
6. res.setHeader(Access-Control-Allow-Methods, GET)
7. res.setHeader(Access-Control-Allow-Headers, city)
8. res.send()
9. })
10.
11. app.get(/, (req, res) {
12. res.setHeader(Access-Control-Allow-Origin, http://127.0.0.1:5500)
13. res.send([{ name: 张三, age: 19 }])
14. })
15.
16. app.listen(8081, () {
17. console.log(服务器成功启动);
18. })前端代码 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. button onclickgetData()获取数据/button
10.
11. script
12. async function getData() {
13. const url http://127.0.0.1:8081/;
14. const result await fetch(url, { method: GET, headers: { city: beijing } });
15. const data await result.json();
16. console.log(data, data);
17. }
18. /script
19. /body
20. /html数据获取到了 预检请求返回的响应头 借助 cors 库快速完成配置 上述的配置中需要自己配置响应头比较麻烦借助cors库可以更方便完成配置 安装cors npm i cors 配置cors 1. const express require(express);
2. const cors require(cors);
3. const app express();
4.
5. // 使用cors中间件
6. app.use(cors({
7. origin: http://127.0.0.1:5500, // 允许的源
8. methods: [GET, POST, PUT, DELETE, HEAD, OPTIONS], // 允许的方法
9. allowedHeaders: [city], // 允许的自定义头
10. exposedHeaders: [abc], // 要暴露的响应头
11. optionsSuccessStatus: 200 // 预检请求成功的状态码
12. }))
13.
14. app.get(/, (req, res) {
15. res.setHeader(abc, 123)
16. res.send([{ name: 张三, age: 19 }])
17. })
18.
19. app.listen(8081, () {
20. console.log(服务器成功启动);
21. })
22. 成功获取数据 第二种JSONP 解决跨域问题 JSONP 概述 JSONP 是利用了script标签可以跨域加载脚本且不受严格限制的特性可以说是程序员智慧的结晶早期一些浏览器不支持 CORS 的时可以靠 JSONP 解决跨域(现在基本不用了)。 基本流程 第一步客户端创建一个script标签并将其src属性设置为包含跨域请求的 URL同时准备一个回调函数这个回调函数用于处理返回的数据。第二步服务端接收到请求后将数据封装在回调函数中并返回。第三步客户端的回调函数被调用数据以参数的形势传入回调函数。 示例代码 前端 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. script
10. function callback(data) {
11. console.log(data, data)
12. }
13. /script
14. script srchttp://127.0.0.1:8081/users/script
15. /body
16. /html后端 1. const express require(express);
2. const app express();
3.
4. app.get(/users, (req, res) {
5. res.send(callback([{ name: 张三, age: 19 }]))
6. })
7.
8. app.listen(8081, () {
9. console.log(服务器成功启动);
10. })结果 优化下代码 前端 1. !DOCTYPE html
2. html langen
3.
4. head
5. meta charsetUTF-8
6. meta nameviewport contentwidthdevice-width, initial-scale1.0
7. titleDocument/title
8. /head
9.
10. body
11. button onclickgetUsers()获取用户/button
12.
13. script
14. function test(data) {
15. console.log(data, data)
16. }
17. function getUsers() {
18. // 创建script元素
19. const script document.createElement(script)
20. // 指定script的src属性
21. script.src http://127.0.0.1:8081/users?callbacktest
22. // 将script元素添加到body中触发脚本加载
23. document.body.appendChild(script)
24. // script标签加载完毕后移除该标签
25. script.onload () {
26. script.remove()
27. }
28. }
29. /script
30. /body
31.
32. /html后端 1. const express require(express);
2. const app express();
3.
4. const users [
5. { name: 张三, age: 19 },
6. { name: 李四, age: 20 }
7. ]
8.
9. app.get(/users, (req, res) {
10. const { callback } req.query
11. res.send(${callback}(${JSON.stringify(users)}))
12. })
13.
14. app.listen(8081, () {
15. console.log(服务器成功启动);
16. })效果 用jQuery封装jsonp 1. $.getJSON(http://127.0.0.1:8081/teachers?callback?, (data) {
2. console.log(data)
3. })第三种配置代理服务器解决跨域 这里需要用到http-proxy-middleware这个包来配置代理服务器 下载http-proxy-middleware npm i http-proxy-middleware 前端 1. !DOCTYPE html
2. html langen
3. head
4. meta charsetUTF-8
5. meta nameviewport contentwidthdevice-width, initial-scale1.0
6. titleDocument/title
7. /head
8. body
9. button onclickgetNews()获取头条数据/button
10.
11. script
12. async function getNews() {
13. const url http://127.0.0.1:8081/api/hot-event/hot-board/?origintoutiao_pc;
14. const result await fetch(url);
15. const data result.json();
16. console.log(data, data);
17. }
18. /script
19. /body
20. /html后端 1. const express require(express);
2. const app express();
3. const { createProxyMiddleware } require(http-proxy-middleware);
4.
5. app.use(express.static(./public))
6.
7. app.use(/api, createProxyMiddleware({ // 拦截所有带有/api的请求
8. target:https://www.toutiao.com, // 转发的目标
9. changeOrigin:true, // 允许跨域
10. pathRewrite:{
11. ^/api: // 把路径中的/api去掉
12. }
13. }))
14.
15. app.listen(8081, () {
16. console.log(服务器成功启动);
17. })
18. 需要把前端代码当成静态资源部署在服务器上 目录 把服务器启动了需要去http://127.0.0.1:8081获取页面 点击获取数据 数据成功获取