常见跨域解决方案以及Ocelot 跨域配置

Intro

我们在使用前后端分离的模式进行开发的时候,如果前端项目和api项目不是一个域名下往往会有跨域问题。今天来介绍一下我们在Ocelot网关配置的跨域。

什么是跨域

跨域:

浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了.

上面提到的,同域的概念又是什么呢??? 简单的解释就是相同域名,端口相同,协议相同

同源策略:

请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.

比如:我在本地上的域名是study.cn,请求另外一个域名一段数据

这个时候在浏览器上会报错:

这个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险~

study.cn/json/jsonp/jsonp.html

当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。

请求地址 形式 结果
http://study.cn/test/a.html 同一域名,不同文件夹 成功
http://study.cn/json/jsonp/jsonp.html 同一域名,统一文件夹 成功
http://a.study.cn/json/jsonp/jsonp.html 不同域名,文件路径相同 失败
http://study.cn:8080/json/jsonp/jsonp.html 同一域名,不同端口 失败
https://study.cn/json/jsonp/jsonp.html 同一域名,不同协议 失败

跨域几种常见的解决方案

解决跨域问题有几种常见的解决方案:

跨域资源共享(CORS)

通过在服务器端配置 CORS 策略即可,每门语言可能有不同的配置方式,但是从本质上来说,最终都是在需要配置跨域的资源的Response上增加允许跨域的响应头,以实现浏览器跨域资源访问,详细可以参考MDN上的这篇CORS介绍

JSONP

JSONP 方式实际上返回的是一个callbak,通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。

原生实现:

  1. <script>

  2. var script = document.createElement('script');

  3. script.type = 'text/javascript';

  4. // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数

  5. script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';

  6. document.head.appendChild(script);

  7. // 回调执行函数

  8. function handleCallback(res) {

  9. alert(JSON.stringify(res));

  10. }

  11. </script>

服务端返回如下(返回时即执行全局函数):

  1. handleCallback({"status": true, "user": "admin"})

jquery ajax

  1. $.ajax({

  2. url: 'http://www.domain2.com:8080/login',

  3. type: 'get',

  4. dataType: 'jsonp', // 请求方式为jsonp

  5. jsonpCallback: "handleCallback", // 自定义回调函数名

  6. data: {}

  7. });

后端 node.js 代码示例:

  1. var querystring = require('querystring');

  2. var http = require('http');

  3. var server = http.createServer();

  4. server.on('request', function(req, res) {

  5. var params = qs.parse(req.url.split('?')[1]);

  6. var fn = params.callback;

  7. // jsonp返回设置

  8. res.writeHead(200, { 'Content-Type': 'text/javascript' });

  9. res.write(fn + '(' + JSON.stringify(params) + ')');

  10. res.end();

  11. });

  12. server.listen('8080');

  13. console.log('Server is running at port 8080...');

JSONP 只支持 GET 请求

代理

前端代理

在现代化的前端开发的时候往往可以配置开发代理服务器,实际作用相当于做了一个请求转发,但实际请求的api地址是没有跨域问题的,然后由实际请求的api服务器转发请求到实际的存在跨域问题的api地址。

angular 配置开发代理可以参考 angular反向代理配置

后端代理

后端可以通过一个反向代理如(nginx),统一暴露一个服务地址,然后为所有的请求设置跨域配置,配置 CORS 响应头,Ocelot是ApiGateway,也可以算是api的反向代理,但不仅仅如此。

Ocelot 跨域配置

示例代码:

  1. app.UseOcelot((ocelotBuilder, pipelineConfiguration) =>

  2. {

  3. // This is registered to catch any global exceptions that are not handled

  4. // It also sets the Request Id if anything is set globally

  5. ocelotBuilder.UseExceptionHandlerMiddleware();

  6. // Allow the user to respond with absolutely anything they want.

  7. if (pipelineConfiguration.PreErrorResponderMiddleware != null)

  8. {

  9. ocelotBuilder.Use(pipelineConfiguration.PreErrorResponderMiddleware);

  10. }

  11. // This is registered first so it can catch any errors and issue an appropriate response

  12. ocelotBuilder.UseResponderMiddleware();

  13. ocelotBuilder.UseDownstreamRouteFinderMiddleware();

  14. ocelotBuilder.UseDownstreamRequestInitialiser();

  15. ocelotBuilder.UseRequestIdMiddleware();

  16. ocelotBuilder.UseMiddleware<ClaimsToHeadersMiddleware>();

  17. ocelotBuilder.UseLoadBalancingMiddleware();

  18. ocelotBuilder.UseDownstreamUrlCreatorMiddleware();

  19. ocelotBuilder.UseOutputCacheMiddleware();

  20. ocelotBuilder.UseMiddleware<HttpRequesterMiddleware>();

  21. // cors headers

  22. ocelotBuilder.Use(async (context, next) =>

  23. {

  24. if (!context.DownstreamResponse.Headers.Exists(h => h.Key == HeaderNames.AccessControlAllowOrigin))

  25. {

  26. var allowedOrigins = Configuration.GetAppSetting("AllowedOrigins").SplitArray<string>();

  27. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowOrigin, allowedOrigins.Length == 0 ? new[] { "*" } : allowedOrigins));

  28. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowHeaders, new[] { "*" }));

  29. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlRequestMethod, new[] { "*" }));

  30. }

  31. await next();

  32. });

  33. })

  34. .Wait();

这里扩展了一个 Ocelot pipeline 的配置,这样我们可以直接很方便的直接在 Startup 里配置 Ocelot 的请求管道。

核心代码:

  1. ocelotBuilder.Use(async (context, next) =>

  2. {

  3. if (!context.DownstreamResponse.Headers.Exists(h => h.Key == HeaderNames.AccessControlAllowOrigin))

  4. {

  5. var allowedOrigins = Configuration.GetAppSetting("AllowedOrigins").SplitArray<string>();

  6. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowOrigin, allowedOrigins.Length == 0 ? new[] { "*" } : allowedOrigins));

  7. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowHeaders, new[] { "*" }));

  8. context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlRequestMethod, new[] { "*" }));

  9. }

  10. await next();

  11. });

在 HttpRequester 中间件后面添加这个中间件在响应中增加跨域请求头配置,这里先判断了一下下面的api有没有配置,如果已经配置则不再配置,使用下游api的跨域配置,这样一来,只需要在网关配置指定的允许跨域访问的源即使下游api没有设置跨域也是可以访问了

需要说明一下的是如果想要这样配置需要 Ocelot 13.2.0 以上的包,因为之前 HttpRequester 这个中间件没有调用下一个中间件,详见 https://github.com/ThreeMammals/Ocelot/pull/830

Reference

  • https://developer.mozilla.org/zh-CN/docs/Web/HTTP/AccesscontrolCORS

  • https://segmentfault.com/a/1190000011145364

  • https://github.com/ThreeMammals/Ocelot/pull/830

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

常见跨域解决方案以及Ocelot 跨域配置相关推荐

  1. html 跨域_常见跨域解决方案以及Ocelot 跨域配置

    常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和api项目不是一个域名下往往会有跨域问题.今天来介绍一下我们在Ocelot网关配置的跨域 ...

  2. Cookie 跨域解决方案(IFrame跨域)

    IFrame跨域思路:假设有a.haorooms.com/text.html和b.haorooms.com/text.html两个页面,通过a.haorooms.com/text.html页面去修改b ...

  3. Vue项目 跨域 解决方案与 vue.config.js 配置解析

    为什么会出现跨域? 出于浏览器的同源策略限制.同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说 ...

  4. 常见js跨域解决方案

    以下为几种常见js跨域解决方案: ajax跨域请求 一.使用jsonp方式实现跨域请求 $.ajax({async: false, type:"POST",dataType: 'j ...

  5. Django中的跨域解决办法 基于后端的跨域解决方案

    Django中的跨域解决办法 基于后端的跨域解决方案 1 何为跨域 在浏览器中,只要发送请求的URL的协议.域名.端口号这三者中的任意一个与当前页面地址的协议.域名.端口号不同,则称之为跨域.当发生这 ...

  6. 前端常见跨域解决方案

    前端常见跨域解决方案 参考文章: (1)前端常见跨域解决方案 (2)https://www.cnblogs.com/plBlog/p/11430457.html 备忘一下.

  7. 9种常见的前端跨域解决方案

    9种常见的前端跨域解决方案(详解) 2019.09.02 21:54 73879浏览 一.什么是跨域?   在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制. ...

  8. 前端常见的跨域解决方案

    一.什么是跨域 跨域也称为非同源策略请求,就是去非同源地址获取数据的行为 只要页面,向非同源地址,发出了ajax / fetch请求,此时就出现了跨域问题. 专业的解释是,两个不同源的服务去访问对方的 ...

  9. 最常见的六种跨域解决方案

    目录: 前言:什么是跨域? JSONP CORS 搭建Node代理服务器 Nginx反向代理 postMessage Websocket 总结 前言:什么是跨域? 跨域就是当在页面上发送ajax请求时 ...

最新文章

  1. Centos 6.4下MySQL备份及还原详情介绍
  2. java二维数组矩阵_java使用二维数组开发五子棋
  3. 基于运放AD8606的信号缓冲小板
  4. 点亮Web的灯---silverlight
  5. 飞桨PaddlePaddle升级解读 | PaddleDetection物体检测统一框架
  6. linux上传文件到服务器
  7. 搭建NFS使多个服务器中的web项目共享图片资源
  8. 进程管理利器Supervisor--入门简介
  9. bat 判断文件名字含有某些字段_PE文件头及其简单逆向运用
  10. java tomcat热部署_intellij idea tomcat热部署配置教程
  11. limits.conf详解
  12. 马斯克都不懂的 GraphQL,API 网关又能对其如何理解?
  13. node.js笔记第一天
  14. 如何用柔和的方法提高QQ浏览器打开网页的速度
  15. 要成为一个牛逼程序猿,你要勇于尝试这10种姿势
  16. 子墨对酒《三国杀》里论模式(一)工厂模式
  17. 黑马股票底部特征和2018年黑马股票池
  18. Intellij Idea version 2021.1.1 鼠标悬停备注的设置
  19. 随机抽奖程序(每天一个python小项目)
  20. 分布式存储高性能的好帮手--RDMA

热门文章

  1. css段落缩进_如何缩进Google文档中的段落
  2. Hadoop/HDFS命令
  3. vue-cli 3.0配置webpack目录别名alias
  4. 一张图解决Android Studio 项目运行按钮灰色
  5. 《Network Warrior中文版(第2版)——思科网络工程师必备手册》一3.3 自动协商故障...
  6. POJ2184 Cow Exhibition(DP:变种01背包)
  7. php如何读出xml的节点内容 两个例子
  8. Xamarin效果第十五篇之自定义CheckBox
  9. 日志文件记录的重要性
  10. C# 10 新特性 —— 补充篇