EnjoyingSoft之Mule ESB实施案例开发分享:在MuleESB中启用CORS

我们在帮助客户使用MuleESB实施的很多场景中,都会遇到CORS的需求。本篇文章,我们将讨论如何通过添加outbound 属性,在Mule中启用CORS跨域资源共享

同源策略&跨域请求

同源策略是Web浏览器实现的一个重要安全概念,用于防止JavaScript跨域发出请求,它不允许来自不同来源的资源之间进行交互。

所谓跨域,当一个请求URL的协议、域名、端口三者之间任意一项与当前浏览的页面URL不同,即为跨域。比如,你通过浏览器访问淘宝首页,该页面上的JavaScript代码想调用天气预报网站上的REST API获取天气情况。从浏览器的角度来看这是两个不同的来源,出于安全原因,浏览器禁止这些类型的请求。

CORS(跨域资源共享)

解决跨域的解决方案就是跨域资源共享(CORS)。CORS引入了一种标准机制,可供所有浏览器用于实现跨域请求。该机制允许网页上的JavaScript调用其他网站提供的REST API。

跨域资源共享(CORS)机制为Web服务器提供跨域访问控制,从而实现安全的跨域数据传输。

CORS的安全问题

需要注意的是,跨域资源共享和Ajax技术会极大地提高用户体验,但同时也会带来很多安全问题,其中最主要的问题来自于CSRF(Cross-site request forgery)跨站请求伪造。

CSRF攻击的大致原理是:

  1. 用户通过浏览器,访问正常网站A(例如招商银行,通过用户的身份认证(比如用户名/密码)成功A网站。

  2. 网站A产生Cookie信息并返回给用户的浏览器。

  3. 用户保持A网站页面登录状态,在同一浏览器中,打开一个新的Tab页访问网站B,现代浏览器基本上都是多Tab风格。

  4. 网站B接收到用户请求后,返回一些攻击性代码,请求A网站的资源(例如转账请求)。

  5. 浏览器执行攻击代码,在用户不知情的情况下携带Cookie信息,向网站A发出请求。

  6. 网站A根据用户的Cookie信息核实用户身份(此时用户在A网站是已登录状态),A网站会处理该请求,导致来自网站B的攻击请求被执行。

从上述的CSRF分析中可以看到,允许跨域执行的脚本需要严格控制安全性,可以指定某些公开的资源可以被跨域访问。

CORS如何工作

跨域资源共享标准的工作原理是添加新的HTTP头。在最简单的形式中,请求应用程序在请求头指定一个Origin头,它描述了请求的来源,并且服务器将使用Access-Contol-Allow-Origin头回复,该头指示允许访问的网站来源和服务器资源。

这种HTTP头交换使CORS成为一种安全机制。服务器如果支持CORS,就可以指示允许发出请求的客户端来源。这种机制的优点在于它由浏览器自动处理,Web应用开发人员无需关心其细节。

请求头:

1
2
3
4
5
6
7
8
GET /orders/list HTTP/1.1
Host: www.cmbchina.com
User-Agent: Mozilla/5.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://www.taobao.com

响应头:

1
2
3
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://www.taobao.com
Content-Type: application/json; charset=utf-8

在Mule中启用CORS

我们经常使用Mule开发REST API,如果允许这些API被跨域访问,我们需要将以下属性添加到流中,如下所示。添加以下属性以接受任何来源,方法和请求头,以便允许跨域请求。

1
2
3
<set-property propertyName="Access-Control-Allow-Origin" value="*" doc:name="Access-Control-Allow-Origin" />
<set-property propertyName="Access-Control-Allow-Headers" value="*" doc:name="Access-Control-Allow-Headers"/>
<set-property propertyName="Access-Control-Allow-Methods" value="*" doc:name="Access-Control-Allow-Methods" />

Mule UI配置:

XML配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="corsFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/cors" doc:name="HTTP"/>
<set-payload value="It's OK" doc:name="Set Payload"/>
<set-property propertyName="Access-Control-Allow-Origin" value="*" doc:name="Property" />
<set-property propertyName="Access-Control-Allow-Headers" value="Content-Type, Accept" doc:name="Property" mimeType="application/json"/>
<set-property propertyName="Access-Control-Allow-Methods" value="*" doc:name="Property" />
</flow>
</mule>

我们使用Postman访问,可以看到Mule Server正常返回内容,并设置了允许跨域的响应头。

也可以通过其他网页上的JavaScript来访问这个API,经过验证,这个API是可以被正常跨域访问的。

访问EnjoyingSoft 网站,获取更多Mule ESB实施案例技术分享。

欢迎转载,但必须保留原文和此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。