不再麻烦后端同学的处理跨域问题 |
您所在的位置:网站首页 › get请求数据限制 › 不再麻烦后端同学的处理跨域问题 |
不再麻烦后端同学的处理跨域问题
什么是跨域
每当我们请求后端识别后打开控制台时如果出现了No ‘Access-Control-Allow-Origin’ header is present on the requesting resource 那么这篇文章可能会帮助到你。 跨域是指在网页中,当一个网页试图去访问不同域名下的资源时(比如发送Ajax请求、使用iframe加载其他网页等),会受到同源策略的限制,从而导致无法正常获取数据的情况。 什么是同源策略同源指的是协议、域名、端口都相同的两个网址。 例如:如果您要从domain1.com/api 向domain1.com 提出请求,则该请求将通过。 如果提出向另一个域的请求,www.domain2.com/api ,浏览器将阻止请求。 浏览器之所以限制跨域访问,是出于安全考虑。 如果浏览器不限制跨域访问,那么攻击者就可以伪造请求,访问用户在其他网站上的敏感信息或执行恶意操作。 举一个简单的例子: 假设受害者在网站A上登录了自己的账户,攻击者在网站B上发布了一个诱骗用户点击的链接,链接指向一个恶意网站C,该网站C使用JavaScript代码向网站A发起了一个跨域请求,偷取了受害者在网站A上的敏感信息(例如cookie、用户名、密码等)。 攻击者可以将以下代码嵌入到网站C中,使用XMLHttpRequest对象向网站A发起跨域请求: var xhr = new XMLHttpRequest(); xhr.open("GET", "http://www.domain2.com/user-info", true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { alert(xhr.responseText); // 将获取的敏感信息上传到攻击者的服务器上 // ... } } xhr.send(); 复制代码这段代码在网站C中被执行,向网站A发起了一个跨域请求,偷取了受害者在网站A上的敏感信息。攻击者可以将获取的信息上传到自己的服务器上,用于非法用途,例如冒充受害者登录网站A、窃取账户资金等。 所以跨域访问如果可以打破同源策略,会给个人隐私和财产安全带来极大的威胁。为了保护用户的安全,浏览器限制了跨域访问。 如何优雅的处理每当我们遇到这个问题时,最快的解决方法就是喊后端加一下enable cors,那有没有前端可以自己想办法解决的呢? 有以下三种常用的方式: JSONP 代理的方式 Webpack devserver JSONP大白话,JSONP是一种利用script标签的GET请求实现跨域的技术。 JSONP一个简单的案例: 假设我们有一个网站A,想要获取另一个网站B的数据,但是B和A不在同一个域,因此不能直接访问。 在B网站的服务器端,提供了一个名为getData的接口,可以返回一些数据。为了让A网站可以获取这些数据,B网站在返回数据时将其封装在一个名为callback的回调函数中,并将回调函数的参数作为需要的数据传给A网的。A网站使用JSONP来获取B网站的数据,并指定一个名为handleResponse的回调函数。 B网站后端返回数据的代码如下: var data = { "name": "Alice", "age": 18 }; var callback = req.query.callback; // 获取回调函数的名称 res.send(callback + '(' + JSON.stringify(data) + ')'); // 将数据封装在回调函数中返回 复制代码A网站前端请求代码如下: function handleResponse(data) { console.log(data); } var script = document.createElement('script'); script.src = 'http://www.domain2.com/getData?callback=handleResponse'; document.head.appendChild(script); 复制代码JSONP的优点是可以实现跨域请求,而且兼容性好,几乎所有浏览器都支持。但是它也有一些弊端: 只支持GET请求。因为JSONP是通过动态创建script标签来实现跨域请求的,而script标签只支持GET请求。 数据格式限制。JSONP只能返回JSON格式的数据,无法返回XML格式的数据。 代理的方式大白话,就是自己搭一个本地服务器,通过访问服务器与服务器的关系,跨过浏览器这的同源策略。 我以Nest.js自己搭建一个简单的代理: import { Controller, Post, Req, Res, Body } from '@nestjs/common'; import { HttpService } from '@nestjs/axios'; import { Request, Response } from 'express'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Controller() export class AppController { constructor(private readonly httpService: HttpService) {} @Post('/api') proxy( @Req() request: Request, @Res() response: Response, @Body() data: any, ): Observable { const url = request.query.url as string; const headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; return this.httpService.post(url, data, { headers }).pipe( map((res) => { response.send(res.data); }), ); } } 复制代码在上述代码中,我们通过 @Body() 装饰器来获取请求的数据,并将其作为参数传递给 this.httpService.post() 方法。同时,使用 request.query 来获取请求的地址。在请求成功时,通过 response.send() 方法将响应数据返回给客户端。 原理如下图所示: 如果是大型项目,并且配置了webpack的话。 1.可以在Webpack的配置文件中添加devServer.proxy属性来实现跨域代理。具体实现方式如下: // webpack.config.js module.exports = { // ... devServer: { proxy: { '/api': { target: 'http://www.domain2.com', //需要跨域的url changeOrigin: true, pathRewrite: { '^/api': '' } } } } } 复制代码在上面的代码中,/api会被转发到www.domain2.com 注意,如果在代理配置中设置了changeOrigin为true,则在代理请求时会自动将请求头中的Host字段设置为代理目标的域名,这样就可以绕过浏览器的同源策略,实现跨域请求。 2.在应用中发起请求时,将API请求的路径设置为代理地址即可: axios.get('/api/data') .then(response => { console.log(response.data) }) .catch(error => { console.log(error) }) 复制代码 踩过的坑值得注意的是:当我们去客户端请求前端自己的服务器时,也是需要设置跨域的,因为请求得端口号不同。 结尾路过的小伙伴觉得有用的话,点点赞收藏下哦❤。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |