300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 前端开发--跨域问题的由来及解决方法

前端开发--跨域问题的由来及解决方法

时间:2020-11-22 11:04:18

相关推荐

前端开发--跨域问题的由来及解决方法

#博学谷IT学习技术支持#

目录

浏览器同源策略

为什么浏览器会有跨域限制的问题?

跨域问题演示

CORS

JSONP

浏览器同源策略

浏览器同源策略是浏览器最基本也是最核心的安全功能,它规定客户端脚本在没有明确授权的情况下,不能读写不同源的目标资源。

所谓的同源指的是相同协议,域名和端口号,如果两个资源路径在协议,域名,端口号上有任何一点不同,则它们就不属于同源的资源,

另外在同源策略上,又分为两种表现形式:

第一:禁止对不同页面进行DOM操作

第二:禁止使用XMLHttpRequest向不是同源的服务器发送ajax请求。

为什么浏览器会有跨域限制的问题?

什么是跨域呢?

访问同源的资源是被浏览器允许的,但是如果访问不同源的资源,浏览器默认是不允许的。访问不同源的资源那就是我们所说的跨域。

如下表格所示:

从表中可以看出域名,子域名,端口号,协议不同都属于不同源,当脚本被认为是来至不同源时,均被浏览器拒绝请求。

浏览器对跨域访问的限制,可以在很大的程度上保护用户数据的安全。

第一:假如没有Dom同源策略的限制,就有可能会出现如下的安全隐患

黑客做了一个假的的网站,通过iframe嵌套了一个银行的网站,然后把iframe的高度宽度调整到占据浏览器的可视区域 ,这样用户进入这个假的网站后,看到就是和真正的银行网站是一样的内容。如果用户输入了用户名和密码,这个假的网站就可以跨域访问到所嵌套的银行网站的DOM节点,从而黑客就可以获取到用户输入的用户名和密码了。

第二:如果浏览器没有XMLHttpRequest同源策略限制,黑客可以进行跨站请求伪造(CSRF)攻击,具体方式如下:

(1)用户登录了个人银行页面A,页面A会在Cookie中保存用户信息

(2)后来用户又访问了一个恶意的页面B,在该页面中执行了恶意Ajax请求的代码

(3)这时页面B会向页面A发送Ajax请求,该请求会默认发送用户Cookie信息。

(4)页面A会从请求的Cookie中获取用户信息,验证无误后,就会返回用户的一系列相关的数据,而这些数据就会被恶意的页面B所获取,从而造成用户数据的泄漏。

正是存在这些危险的场景存在,所以同源策略的限制就显得非常总要。

跨域问题演示

创建一个文件夹,在该文件夹中创建index.html文件,该文件中的代码如下:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script>window.onload = function () {var btn = document.getElementById("btnLogin");btn.addEventListener("click", function () {sendRequest();});};function sendRequest() {var userName = document.getElementById("userName").value;//这里为了简单,暂时不考虑浏览器兼容性问题var xhr = new XMLHttpRequest();let url = "http://localhost:3000/getUserNameInfo?name=" + userName;xhr.open("get", url, true);xhr.send();xhr.onreadystatechange = function () {if (xhr.readyState === 4 && xhr.status === 200) {console.log(xhr.responseText);}};}</script></head><body>用户名:<input type="text" id="userName" /> <br /><button id="btnLogin">登录</button></body></html>

在该文件夹下面安装express

npm install express

同时创建server.js文件,该文件的代码如下:

var express = require('express')var app = express();app.get('/getUserNameInfo', function (req, res) {var userName = req.query.name;var result = {id: 10001,userName: userName,userAge:21};var data = JSON.stringify(result);res.writeHead(200, { 'Content-type': 'application/json' })res.write(data);res.end()})app.listen(3000, function () {console.log('服务端启动....')})

下面启动服务端

同时index.html文件也通过vscode自带的服务器进行访问。

这时会出现如下错误:

Access to XMLHttpRequest at 'http://localhost:3000/getUserNameInfo?name=admin'from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

通过以上错误可以发现,现在的程序出现 跨域的问题,

下面看一下具体的解决方案

CORS

通过上面的错误,我们明白了,客户端不能发送跨域请求是因为服务端并不接收跨域的请求,所以为了解决跨域请求的问题,我们可以将服务端设置为可以接收跨域请求。

这里我们需要使用CORS('跨域资源共享'),来解决跨域请求的问题。CORS主要的实现方式是服务端通过对响应头的设置,接收跨域请求的处理。

服务端修改后的代码如下:

var express = require('express')var app = express();app.all('*', function (req, res) {//设置可以接收请求的域名res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');res.header('Access-Control-Allow-Methods', 'GET, POST,PUT');res.header('Access-Control-Allow-Headers', 'Content-Type');res.header('Content-Type', 'application/json;charset=utf-8');req.next();})app.get('/getUserNameInfo', function (req, res) {var userName = req.query.name;console.log('userName=',userName)var result = {id: 10001,userName: userName,userAge:21};var data = JSON.stringify(result);res.writeHead(200, { 'Content-type': 'application/json' })res.write(data);res.end()})app.listen(3000, function () {console.log('服务端启动....')})

在原有的代码中,我们主要是添加了如下的代码:

app.all('*', function (req, res) {//设置可以接收请求的域名res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');res.header('Access-Control-Allow-Methods', 'GET, POST,PUT');res.header('Access-Control-Allow-Headers', 'Content-Type');res.header('Content-Type', 'application/json;charset=utf-8');req.next();})

在上面的代码中,最主要的是res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');这行代码,

这行代码是必须的,表示服务器可以接收哪个域发送的请求,可以用通配符*,表示接收全部的域,但是为了安全,我们最好设置特定的域。我们这里测试的是http://127.0.0.1:5500(注意:如果客户端地址是127.0.0.1,这里不能写成localhost,同时还需要注意,这里地址最后没有/)

后面请求头信息可以根据情况进行选择设置,例如接收请求的方法,数据传输的格式等。

通过对服务端的处理不会对前端代码做任何的处理,但是由于不同系统服务端采用的语言与框架是不同的,所以导致服务端的处理方式不同。

JSONP

JSONP是客户端与服务端进行跨域通信比较常用的解决办法,它的特点是简单,兼容老式浏览器,并且对服务器影响小。

JSONP的实现的实现思想可以分为两步:

第一:在网页中动态添加一个script标签,通过script标签向服务器发送请求,在请求中会携带一个请求的callback回调函数名。

第二: 服务器在接收到请求后,会进行相应处理,然后将参数放在callback回调函数中对应的位置,并将callback回调函数通过json格式进行返回。

前端代码:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script>window.onload = function () {var btn = document.getElementById("btnLogin");btn.addEventListener("click", function () {sendRequest();});};function sendRequest() {var userName = document.getElementById("userName").value;//请求参数,其中包含回调函数var param = "name=" + userName + "&callback=successFn";//请求的urlvar url = "http://localhost:3000/getUserNameInfo?" + param;var script = document.createElement("script");script.src = url;document.body.appendChild(script);}function successFn(result) {console.log("result=", result);}// function sendRequest() {//var userName = document.getElementById("userName").value;////这里为了简单,暂时不考虑浏览器兼容性问题//var xhr = new XMLHttpRequest();//let url = "http://localhost:3000/getUserNameInfo?name=" + userName;//xhr.open("get", url, true);//xhr.send();//xhr.onreadystatechange = function () {// if (xhr.readyState === 4 && xhr.status === 200) {// console.log(xhr.responseText);// }//};// }</script></head><body>用户名:<input type="text" id="userName" /> <br /><button id="btnLogin">登录</button></body></html>

在上面的代码中,我们重新改造了sendRequest方法,在该方法中构建了param参数,该参数的内容包括了用户输入的用户名以及回调函数名。下面构建好所要请求的服务端的url地址,将该url地址交给script标签的src属性,通过该属性向服务器发送请求。

同时定义回调函数successFn,接收服务端返回的数据。可以对服务端返回的数据做进一步的处理。

这里需要注意的一点就是:回调函数必须设置为全局的函数。因为服务端返回响应后,会在全局环境下查找回调函数。

下面看一下服务端的处理:

var express = require('express')var app = express();// app.all('*', function (req, res) {////设置可以接收请求的域名//res.header('Access-Control-Allow-Origin', 'http://127.0.0.1:5500');//res.header('Access-Control-Allow-Methods', 'GET, POST,PUT');//res.header('Access-Control-Allow-Headers', 'Content-Type');//res.header('Content-Type', 'application/json;charset=utf-8');//req.next();// })app.get('/getUserNameInfo', function (req, res) {var userName = req.query.name;//获取请求的回调函数var callbackFn = req.query.callbackconsole.log('callbackFn==',callbackFn)console.log('userName=',userName)var result = {id: 10001,userName: userName,userAge:21};var data = JSON.stringify(result);res.writeHead(200, { 'Content-type': 'application/json' })//返回值是对对回调函数的调用res.write(callbackFn+'('+data+')')// res.write(data);res.end()})app.listen(3000, function () {console.log('服务端启动....')})

在服务的代码中,需要接收回调函数的名称。

同时返回的内容中,包含了回调函数的名称,以及传递给该回调函数的具体数据。

这样当回调函数返回给浏览器后,浏览器可以从全局的环境中查找该回调函数,并进行执行。

使用JSONP的优点与缺点:

优点:

简单,不存在浏览器兼容性的问题

缺点:

只能实现get请求,如果是post请求则无法进行跨域的处理。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。