第三部分:创建更安全的网络程序
概论:创建一个安全的网络程序,你需要考虑很多技术以外的东西。一个安全的解决方案除了前面讲到的虚拟机安全,应用程序安全外,还依赖于你对网络环境的理解以及程序使用者(包括那些居心叵测的用户)的使用技能。在这第三部分,Todd Sundsted安全讨论的最后一部分,他探究了这些问题并最后给出了解决方案。
在这个安全系列讲解中,我一直鼓励你从三个不同方面来考察JAVA安全问题。在头两篇文章中,我主要集中于虚拟机和应用程序安全。这个月,我将讨论最后一部分--“网络安全”。
网络安全处理的是互联的实体之间的通讯管道的安全问题——每个实体都确认来自另一方的身份验证以及基于通讯管道之上的信息真实性。
创建安全的网络程序会面临很多挑战。那些构成现代安全技术(比如加密系统)的论题常常令开发人员感到迷惑。并且,一些关键的标准和技术还是不透明的——比如X.509认证标准。时至今日,网络安全还是一个难题,因为,网络媒体本身的角色就难以理解。
看看下面这个推论:在我们日常交流中,沟通双方的信息交流通过多种媒介进行,比如光和声音。我们凭这些信息去判断他人的身份,鉴定沟通渠道的质量等。即使我们通过电话交流,我们还是可以通过对方在电话一端的语调,语速,走音等细微之处来辨别出信息,而不必通过交谈双方的谈话内容。
而基于如互联网等媒体的通讯则只能提供少的多的线索。设想你和同伴在两间屋子使用一种通话的罐来说话。可以想像,可怜的信号质量湮灭了那些我们借以做出判断的线索。而在互联网或是其它网络上的程序通讯同这种情况是类似的。
网络安全的内容包含了在匿名管道上进行身份验证,避免通讯信息遭到窃听以及意外或是恶意的修改等方面。
我广泛涉猎了用于加强安全通讯的工具以及相应技术(参考http://www.javaworld.com/javaworld/jw-08-2001/jw-0810-howto.html#resources)。这里我更实际的讨论在我们设计以及完成一个网络安全解决方案时所要考虑的事情。
理解你自己要保护什么:
设计一个安全解决方案你首先要从理解需求开始。通过互联网进行金融交易显然比你下载上周体育积分的WEB页面更需要安全。在选择一种技术和开始设计时,你应该考虑一下几个方面:
• 安全设计会增加产品设计及实现的复杂性,以及安装,配置的复杂性,还有对于终端用户也是这样。尽管安全是值得的,但是复杂性则并不是用户所需要的。你打算怎样复杂化你的安全设计呢?
• 安全处理,尤其是加密以及解密,常常都是CPU操作密集型的。多数桌面及服务器系统都有足够强的马力,但是那些缺乏资源的设备,比如蜂窝移动电话,PDAs等常常缺少这种能力。你的目标平台能适于处理这样的负荷吗?
• 同样,安全设计会增加程序代码量。尽管在桌面以及服务器计算机上这个不算太严重的问题,但在嵌入式系统中,这就将会涉及到一些利害关系,特别是那些为JAVA2平台,比如Micro Edition (J2ME)而构建的应用,这样的情况下你又能处理好负荷吗?
比如这里的一个列子,移动信息设备框架(MIDP)第一版,就缺少SSL(安全套接口层)支持——端到端WEB解决方案中最核心的组件——其主要原因就是对于移动设备来说,SSL太过于苯重了。针对这个问题,SUN微系统实验室的Vipul Gupta为J2ME构建了兼容SSL标准的一个实现。他的这一成果表明了小设备也可以达到让人可以接受的SSL性能。Gupta的这一实现之所以能达到这一目标,是因为它只是支持最流行的密码套件,其余的则经过了削减以适应小设备的要求,当然,这种实现缺少服务器要求的客户端验证(一种很消耗的客户端组件),并且它通过多个到服务器的连接重复使用了RSA(Rivest-Shamir-Adleman)计算。你可以看看网址:http://www.javaworld.com/javaworld/jw-08-2001/jw-0810-howto.html#resources,可以找到更多的信息。
使用合适的技术:
选择一种合适的技术对于实现一种网络安全解决方案来说似乎已经不用多说了。这样的选择将会影响到安全的寿命和质量。JDK提供了大量的安全API函数。下面这张表将有助你为你的方案选择合适的技术。
• 验证和数字签名:JAVA密码系统(java.security)
• 加密/解密和消息验证代码:JAVA密码系统扩展(javax.crypto)
• X.509验证:JAVA密码系统(java.security.cert)
• 可插入的验证和授权:JAVA验证和授权服务(javax.security.auth)
JSK1.4测试版包括:
• Kerberos:GSS(通用安全服务)API(org.ietf.jgss)
• 证书路径确认:证书路径确认API(java.security.cert)
这些标准API处理了大量安全相关的WEB程序以及企业整合任务的问题。
理解网络:
不考虑网络来进行网络安全方案设计显然是不明智的。程序所运行的系统以及基于其上的网络都将在方案设计中给予充分的考虑。
设想一下这个情景:你建立了一个运行在安全网络之上的程序。如果网络确实是安全的——这意味着网络在物理上给保护起来,用户是可信赖的,并经过了仔细的授权——那么在这种情况下你就可以尽量少的关心你程序本身的安全问题。但是,在多数情况下,网络并非如所想像的那样安全,而且开发人员在开发安全系统中往往失败,因为不含安全机制的系统要比有安全机制的系统创建起来要难得多。然而,一些情况证实了这个方法。比如,在一个群集系统中运行了多个程序,并相互通讯,进行负载平衡,这样的情形就有足够的理由要求这个集群成为一个安全的整体,而不是程序本身。
更实际的讲,保护你的程序典型情况下意味着评估运行程序的机器的安全,机器安装环境的安全以及网络,包括接入点。
对接入点进行验证非常重要。对来自针对程序的恶意攻击,我们还可以设下“陷阱”,就是提供这样的一个入口,这个接入点为蛰伏的sniffer,嗅探器活动提供了一个窗口(sniffer是一种代码片断,用于侦听网络通信信息)。通过sniffer收集来的信息可以提供程序的入口。
理解合法使用者和滥用者:
你要记住,所谓的安全解决方案始终是围绕人来建立的,因此你必须理解程序使用者以及不怀好意者的能力和技术。那些“滥用者”,通常比正常用户更精于技术,他们让事情变得更复杂。
在你考虑设计你的程序安全方案时,你必须要考虑那些使用者的技能水平。比如,如果你的用户坚持要把密码记在碎纸上并在监视器上敲打进去,那么你就不必开发出强大的基于密码的安全系统。正如多数人所说,通常境况下,最好的安全是花费预算来进行培训。
对于滥用着来说,事情又有所不同。这些人常常更具有技术天赋,并更易于受到激励,这就要求更强的技术防护,即时的升级补丁包以及警醒的告诫。
全面掌握JAVA安全:
没有强大的网络安全,你的程序以及数据将是不稳定的。我讲过的其它的两部分——虚拟机安全,应用程序安全——和网络安全一起为JAVA程序提供了一个全面的安全图景。为了构建安全的JAVA程序,你必须全面理解以上的三个方面。