加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > C语言 > 正文

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

发布时间:2020-12-15 02:16:41 所属栏目:C语言 来源:网络整理
导读:常见跨域解决方案以及Ocelot 跨域配置 Intro 我们在使用前后端分离的模式进行开发的时候,如果前端项目和api项目不是一个域名下往往会有跨域问题。今天来介绍一下我们在Ocelot网关配置的跨域。 什么是跨域 跨域: 浏览器对于javascript的同源策略的限制,例如a

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

Intro

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

什么是跨域

跨域:

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

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

同源策略:

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

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

image

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

image

这个就是同源策略的保护,如果浏览器对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>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

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

handleCallback({"status": true,"user": "admin"})
  1. jquery ajax:
$.ajax({
    url: 'http://www.domain2.com:8080/login',type: 'get',dataType: 'jsonp',// 请求方式为jsonp
    jsonpCallback: "handleCallback",// 自定义回调函数名
    data: {}
});

后端 node.js 代码示例:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request',function(req,res) {
    var params = qs.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回设置
    res.writeHead(200,{ 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');

    res.end();
});

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

JSONP 只支持 GET 请求

代理

  1. 前端代理

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

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

  1. 后端代理

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

Ocelot 跨域配置

示例代码:

app.USEOcelot((ocelotBuilder,pipelineConfiguration) =>
                {
                    // This is registered to catch any global exceptions that are not handled
                    // It also sets the Request Id if anything is set globally
                    ocelotBuilder.UseExceptionHandlerMiddleware();
                    // Allow the user to respond with absolutely anything they want.
                    if (pipelineConfiguration.PreErrorResponderMiddleware != null)
                    {
                        ocelotBuilder.Use(pipelineConfiguration.PreErrorResponderMiddleware);
                    }
                    // This is registered first so it can catch any errors and issue an appropriate response
                    ocelotBuilder.UseResponderMiddleware();
                    ocelotBuilder.UseDownstreamRouteFinderMiddleware();
                    ocelotBuilder.UseDownstreamRequestInitialiser();
                    ocelotBuilder.UseRequestIdMiddleware();
                    ocelotBuilder.UseMiddleware<ClaimsToHeadersMiddleware>();
                    ocelotBuilder.UseLoadBalancingMiddleware();
                    ocelotBuilder.UseDownstreamUrlCreatorMiddleware();
                    ocelotBuilder.USEOutputCacheMiddleware();
                    ocelotBuilder.UseMiddleware<HttpRequesterMiddleware>();
                    // cors headers
                    ocelotBuilder.Use(async (context,next) =>
                    {
                        if (!context.DownstreamResponse.Headers.Exists(h => h.Key == HeaderNames.AccessControlAllowOrigin))
                        {
                            var allowedOrigins = Configuration.GetAppSetting("AllowedOrigins").SplitArray<string>();
                            context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowOrigin,allowedOrigins.Length == 0 ? new[] { "*" } : allowedOrigins));
                            context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlAllowHeaders,new[] { "*" }));
                            context.DownstreamResponse.Headers.Add(new Header(HeaderNames.AccessControlRequestMethod,new[] { "*" }));
                        }
                        await next();
                    });
                })
                .Wait();

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

核心代码:

// cors headers
                    ocelotBuilder.Use(async (context,new[] { "*" }));
                        }
                        await next();
                    });

在 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/Access_control_CORS
  • https://segmentfault.com/a/1190000011145364
  • https://github.com/ThreeMammals/Ocelot/pull/830

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读