使用 SSL 加密保护 Flex 到 Axis 单点登录解决方案





0/5 (0投票)
本文解释了如何使用 SSL 保护 Flex 客户端、基于 Axis 的服务和 OpenSSO 服务器之间的连接。
引言
在我们的上一篇文章“使用 Axis 和 Flex 构建和查询安全 SSO 服务”中,我们描述了如何创建基础设施,以便 Flex 应用程序使用单点登录技术访问 Axis2 Web 服务。上一篇文章中描述的系统在不同服务器之间传输数据。这些数据包含服务返回给客户端的私有信息,以及授予已登录身份提供者服务器的授权用户的安全令牌。由于传输的数据通过 HTTP 未加密地传输,攻击者可以:
- 读取服务返回的您的
私有
数据 - 向您的客户端应用程序传递其自己的虚假数据,而不是服务数据
- 使用您的安全令牌读取您有权访问的所有服务中的数据
本文将为您提供如何使用 SSL 加密保护这些连接的提示,这将大大减少此类未经授权行为的可能性。
关于本文不涉及的内容
- 这不是一篇独立的文章,建议您只有在对上一篇文章感兴趣时才阅读。
- 本文不是关于如何创建生产环境的详细指南,也没有描述如何配置和使用受信任的 SSL 证书。
本文的目的是演示我们示例系统所做的所有连接如何配置为使用 SSL 加密。我们还将彻底检查这些连接以确保它们是安全的。
为了向您提供一个工作示例,我们将使用*自签名 SSL 证书*。请注意,使用自签名证书并不能保护您免受可能的“中间人”攻击(请参阅何时可以使用自签名证书)。在生产环境中,您应该使用有效证书,例如来自商业或免费证书颁发机构的证书(请参阅www.sslshopper.com网站,其中包含大量有关此主题的信息)。
准备环境
我们假设您已阅读上一篇文章并执行了其中描述的所有步骤,以建立一个工作环境,其中包含:
- 已启动并运行 OpenSSO 身份提供者,并在其上定义了示例角色。
- 已配置的 Axis2 安装,并部署了示例服务(
MathService
和StringService
)。PermissionChecker_mapping.properties文件包含示例身份提供者角色和示例服务权限之间的映射。 - 在 Web 服务器上可用的示例客户端应用程序(
SSOWSPrototype
)。
此外,我们将使用 Fiddler 应用程序来检查连接。

为简化起见,在本文和前几篇文章中,我们假设所有测试都在一台开发机器上进行。这意味着所有应用程序都在运行,并且客户端应用程序托管在该机器上的同一 Tomcat 实例中。Fiddler 应用程序也在这台机器上执行。如果您计划构建一个与上述不同的真实环境,则需要自行处理,但我们希望此处提供的信息能使这项任务更容易。
分析要保护的区域
首先,我们需要分析数据交换过程并定义需要保护的连接。在我们的基础设施中,进行了以下连接:

- 客户端与服务提供者之间的连接
- 客户端与身份提供者之间的连接
- 服务与身份提供者之间的连接
我们的目标是使它们都使用 SSL 加密工作。
在 Tomcat 服务器上启用 SSL 支持
首先,我们需要配置运行我们应用程序的 tomcat 服务器以支持 SSL。
我们现在将创建一个自签名证书(在生产环境中,您应该使用有效证书)。为了生成证书密钥库和自签名证书本身,我们将使用 Java 的*keytool*。
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
在显示的控制台应用程序中,指定一个密钥库密码(默认应为“changeit”)。对于其余设置,指定您想要的任何数据。此命令将在用户的主目录中创建一个名为“.keystore".
现在我们将启用 Tomcat 服务器中的 SSL 支持。转到/conf/server.xml文件,取消注释 SSL HTTP/1.1 Connector
条目。为简单起见,我们将使用 https 协议的默认端口 443
,而不是 8443
端口。该条目应如下所示:
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150"
scheme="https" secure="true" clientAuth="false" sslProtocol="TLS"
keystoreFile="${user.home}/.keystore" keystorePass=" changeit "/>
注意:如果您在创建密钥库时使用了非默认密码,请将keystorePass
值替换为正确的密码。如果您将生成的密钥库文件从用户主目录移动到其他位置,则需要在keystoreFile
属性中定义该位置。
准备服务器端 Java 以使用 Fiddler
由于我们将使用 *Fiddler* 来检查连接,因此我们需要对配置进行一些更改,以便服务器端 Java 将通过 Fiddler 执行调用,我们将能够看到所有服务器端请求。
首先,我们需要告诉服务器端 Java 使用 Fiddler 作为代理。为此,我们将以下字符串
添加到 Tomcat 启动文件(catalina.bat在 Windows 上),其中我们指定 Fiddler 将运行的机器的地址和端口(在我们的例子中,这是 127.0.0.1:8888
)
set CATALINA_OPTS=-DproxySet=true -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8888
-Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=8888
即使定义了代理,服务器端 Java 也不会为 *localhost* 调用代理。这就是为什么在我们后续的配置中,我们将使用一个虚假域名,而不是 localhost
。例如,让它成为 *"www.ssoinaction.org"*。为了让我们的系统能够识别这个域名,我们将使用 Fiddler 添加一个适当的映射(我们将为此转到 Fiddler 的 *Tools -> HOSTS* 菜单)。由于 Fiddler 和所有服务都在同一台本地机器上运行,因此映射将如下所示:127.0.0.1 www.ssoinaction.org

另一件事是 Fiddler 通过向客户端提供自己的自签名 SSL 证书来监视安全连接(我们稍后会讨论)。因此,我们需要让我们的服务端客户端(连接到身份提供者)能够接受该自签名证书。为了在我们的测试环境中实现这一点,我们将定义一个完全信任的证书管理器(请注意,您不应在生产环境中使用这种技巧)。由于我们需要在 Tomcat 引导程序上安装该管理器,我们将所需的代码放入 javax.servlet.ServletContextListener
。实现此接口的 CertFix
类在源代码项目中可用(为了编译它,您需要将servlet-api.jar,位于 tomcat 安装的 *lib* 文件夹中,添加到项目构建路径)。我们应该将编译后的项目类打包成 *jar* 文件,并将该 *jar* 放置到/webapps/axis2/WEB-INF/libTomcat 安装的文件夹。为了注册监听器,我们应该将以下内容添加到/webapps/axis2/WEB-INF/web.xml文件在 <web-app>
标签下
<listener>
<listener-class>CertFix</listener-class>
</listener>
保护客户端到服务连接
现在,我们需要使 Flex 客户端应用程序能够使用 SSL 访问服务。为此,我们唯一需要做的就是从安全的 https 链接加载应用程序本身。如果您希望 Flex 客户端应用程序从 http 下载,您将需要对服务器配置文件进行一些额外的更改(请参阅使用 HTTPS)。
确保 Fiddler 正在运行。由于我们使用 SSL,我们将在 Fiddler 中启用“*解密 HTTPS 流量*”选项(此设置可在 *工具 -> Fiddler 选项 -> HTTPS* 中找到),这样我们将能够看到实际传输的数据。有趣的是,Fiddler 用来解密 SSL 流量的方法是一个很好的“中间人”示例,我们之前提到过。Fiddler 将自己的 SSL 证书提供给客户端,解密提供的数据,用服务器证书加密并将其发送到服务器(好消息是 Fiddler 不是攻击者)。
要加载 Flex 应用程序,我们打开浏览器。由于我们在同一台机器上运行 Fiddler,它会自动作为浏览器的代理(如果您想在不同的机器上运行浏览器,您需要手动将 Fiddler 定义为浏览器的代理)。
现在,由于我们的应用程序位于已启用 https 的 Tomcat 服务器上,我们可以使用以下 URL:
https://www.ssoinaction.org/flex-client/SSOWSPrototype.html
如果我们的服务器证书是自签名的(这就是我们的情况),Fiddler 将显示一条关于证书不正确的消息,我们应该接受它。

之后,浏览器将显示一条消息,表明该证书是自签名证书。顺便说一句,这正是攻击者在使用自签名证书时可以对我们进行欺骗的地方。它可以传递自己的自签名证书,然后我们将处理完全解密并受攻击者控制的流量。

请注意,即使您的服务器使用受信任的证书,您也会收到此屏幕——这是因为 Fiddler 向浏览器提供了自己的自签名证书。但是,由于我们信任 Fiddler 并且正在测试环境中工作,我们接受了证书。我们的客户端界面打开。

现在,我们将使用客户端联系 *Math* 服务。为了使此连接安全,我们将通过在 Math Web 服务 URL 字段中将 *https://:8080* 替换为 *https://www.ssoinaction.org* 来将调用从 *http* 更改为 *https*。为方便起见,您还可以获取客户端源代码,替换源代码中的服务 URL(查找带有 id="wsdlUrl"
属性的 mx:TextInput
元素),然后重新编译客户端应用程序。
现在,我们输入一些数字,然后点击“=”号。

由于我们尚未授权,因此出现登录对话框。

要分析幕后发生的事情,让我们看看 Fiddler。在 Fiddler 应用程序的“*Web 会话*”区域中,有我们对 Math 服务 *wsdl* 的调用,并且它使用 HTTPS。

但正如你所看到的,还有另一个可用的调用,它指向 URL http://www.ssoinaction.org:8080/axis2/services/
并且它是不安全的。
MathService.MathServiceHttpSoap11Endpoint/
这是因为当客户端调用 wsdl 文件时,它并没有收到实际的服务数据,而是服务配置。此配置包含获取实际数据的 URL。在我们的示例服务中,wsdl 文件没有显式定义,而是自动生成的。让我们转到 Fiddler,查看 https://www.ssoinaction.org/axis2/services/MathService?wsdl
URL 响应内容。为了查看调用的内容,切换到“*Inspectors*”选项卡并为响应启用“*Raw*”视图(我们可以看到该数据,因为我们在 Fiddler 设置中启用了“*Decrypt HTTPS traffic*”选项)。在那里,您将看到以下内容:
<wsdl:service name="MathService">
<wsdl:port name="MathServiceHttpSoap11Endpoint"
binding="ns:MathServiceSoap11Binding">
<soap:address location="http://www.ssoinaction.org:8080/axis2/services/
MathService.MathServiceHttpSoap11Endpoint/"/>
</wsdl:port>
<wsdl:port name="MathServiceHttpSoap12Endpoint" binding="ns:MathServiceSoap12Binding">
<soap12:address location="http://www.ssoinaction.org:8080/axis2/
services/MathService.MathServiceHttpSoap12Endpoint/"/>
</wsdl:port>
<wsdl:port name="MathServiceHttpEndpoint" binding="ns:MathServiceHttpBinding">
<http:address location="http://www.ssoinaction.org:8080/axis2/services/
MathService.MathServiceHttpEndpoint/"/>
</wsdl:port>
</wsdl:service>
正如我们所看到的,所有生成的端点都使用 *http* 协议。这意味着即使我们使用 *https* 调用服务 wsdl,wsdl 也包含指向服务数据的 http 样式链接,结果,这些数据将以不安全的方式传输。
因此,我们需要配置 *wsdl* 生成的内部,使其与 SSL 配合使用,从而包含 https 样式的 URL。
首先,我们将配置 Axis2 以支持 https。打开/webapps/axis2/WEB-INF/conf/axis2.xml从 tomcat 安装文件夹中删除文件并添加新的*传输接收器*
<transportReceiver name="https"
class="org.apache.axis2.transport.http.SimpleHTTPServer">
<parameter name="hostname">https://www.ssoinaction.org</parameter>
</transportReceiver>
之后,我们需要告诉 Axis,我们的服务将使用 *https* 传输。打开/META-INF/services.xml文件,位于/webapps/axis2/WEB-INF/services/MathService.aar存档并在 <service>
元素下添加以下内容
<transports>
<transport>https</transport>
</transports>
对 String
服务执行相同操作。
之后,重启 tomcat 服务器,在浏览器中重新打开客户端,然后再次点击“=”号联系 Math 服务。现在看看 Fiddler。

如您所见,现在对服务的两个调用都通过 HTTPS 进行。
保护客户端和服务与身份提供者的连接
查看对服务的第二个 HTTPS 调用的响应内容。在该调用中,由于我们尚未获得授权,服务返回了一个错误。提供的 SOAP 消息中包含 identityProviderUrl
(此服务身份提供者的 WSDL)。如您所见,它不安全,因此我们需要配置 OpenSSO 服务以使用 HTTPS。我们将以与保护与 Math
和 String
服务的连接相同的方式进行操作。
首先,我们将通过访问/webapps/axis2/WEB-INF/spring-webapp.xml并将 identityProviderUrl
更改为 https,使其看起来像这样
<property name="identityProviderUrl"
value="https://www.ssoinaction.org/opensso/identityservices?wsdl"/>
其次,我们将通过访问/webapps/opensso/WEB-INF/wsdl/IdentityServices.wsdl文件并更改 *IdentityServicesImplService 地址位置*,使其看起来像这样
<service name="IdentityServicesImplService">
<port name="IdentityServicesImplPort"
binding="tns:IdentityServicesImplPortBinding">
<soap:address location="https://www.ssoinaction.org/opensso/
identityservices/IdentityServices"></soap:address>
</port>
</service>
从现在开始,客户端应用程序将通过 SSL 与身份提供者交互。由于 Math
和 String
服务像客户端一样从spring-webapp.xml文件,与身份提供者的连接也将变得安全。
进行最终测试
由于我们已经配置好所有内容,现在可以进行最终安全检查了。
为了使其更加严格,我们将完全禁用 Tomcat 服务器的 HTTP 连接器,以便唯一接受的连接是 SSL 调用。转到/conf/server.xmlTomcat 服务器的文件并注释掉 *8080* 连接器
<!--<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />-->
这将确保,如果我们犯了错误并且某些连接仍然不安全,我们的测试将失败,因为现在不允许以不安全的方式从服务器获取数据。
现在我们重启 tomcat 服务器,并按照我们已经做过的步骤打开客户端应用程序,直到出现登录对话框。然后我们将使用上一篇文章中创建的“test”用户进行授权。成功登录后,我们将最终从 Math
服务接收到计算结果。

让我们看看 Fiddler,看看建立了哪些连接。

客户端应用程序调用了 Math 服务,服务告诉我们需要在身份提供者上进行授权(前两次调用)。客户端在身份提供者上授权了我们(接下来的两次调用),然后再次调用 Math 服务以接收计算结果(第五次调用)。Math 服务又联系了身份提供者服务,以检查我们是否被允许执行“加法”操作(最后两次调用)。
正如我们所看到的,所有这些连接现在都是安全的。
资源
- Fiddler 下载页面
- SSL 比较与评论
- SSL 配置操作指南
- Java 的 SSL 信任提供者
- 传输安全 (SSL) 解决方法
- 使用 HTTPS
- 使用 SSL
- 生成的 WSDL HTTPS 端口不是 8443
历史
- 这是本文的第一个修订版。