一、WSSecurity简述
安全的Web服务是Web服务成功的必要保证。但大家都知道,Web服务使用XML来进行数据交换,而XML在默认情况下是明文编码的;同时,大部分Web服务使用HTTP协议作为传输协议,同样,HTTP也是使用明文方式来传输数据的。这就造成了在不加密的传输协议上传输不加密的信息,从而使信息传输的保密性受到威胁。作为企业级的应用,以上的方式不能满足安全性基本要求:
- 数据在internet上传输的时侯是不应该被第三方能够看到的;
- 双方必须能够验定彼此间的来源;
- 双方必须能够确定被传送的数据没有被在中途中遭到黑客的修改。
通过使用SSL协议我们可以解决第一个问题即:”不应该被第三方看到”;使用数字签名和数字证书可以解决后面的两个问题。当使用数字证书方法时,Web 服务请求者必须有一个由可信认证中心签署的数字证书。请求者使用这个证书来表明它们的身份,并对 SOAP 消息进行数字签名。对方系统接收到消息后,就可对消息做时间戳记并进行日志记录。此时,数字签名会得到验证。验证过程将确保消息来自发送方,并且还要验证消息内容在传输过程中没有被篡改。
IBM、Microsoft 和 Verisign 于2002年十二月份联合发布了一个关于 Web 服务安全性(Web Services Security,WS-Security)的规范,该规范描述如何向 SOAP 消息附加签名和加密报头;另外,它还描述如何向消息附加安全性令牌(包括二进制安全性令牌,如 X.509 证书),提供了一套帮助 Web 服务开发者保护 SOAP 消息交换的机制。
根据应用的对安全要求的级别不同,可以采用不同的方式来实现安全性,以下是目前最常用的一些实现方式(从低到高排列):
- J2EE Web应用默认的访问控制(数据是明文的);
- 使用axis的Handler进行访问控制(数据是明文的);
- 使用Servlet过滤器(Filter)进行访问控制(数据是明文的);
- 使用SSL/HTTPS协议来传输(加密的数据传输协议);
- 使用WS-Security规范对信息进行加密与身份认证(数据被加密传输)。
前三种方式对于安全级别要求不高的应用是可行的,它能够使用Web应用访问认证机制来进行权限验证,从而保护对资源的访问。但需要注意的是,虽然它们进行了身份验证,但信息的传递还是以明文的方式进行的,不能保证信息在传输过程中不被窃取。SSL是一个安全的传输协议,使用它传输Web服务能保证信息不被第三方窃取。但它有个缺点就是对系统资源消耗大。采用最后一种方式,信息被签名后再加密,然后把加密后的信息网络上传播,这样,即使第三方获得加密后的传输信息,也不能解密。对于安全级别要求高的系统,应该采用WS-Security规范来作为Web服务安全性解决方案。
二、基于https通信并且使用用户名密码来验证的WS
在一般的应用中,我们可以通过https来保护我们传输的明文数据。
关键在于我们需要来验证这个客户端过来的请求,即需要具有基本的用户名,密码才能访问我的Web Service,我们称之为Basic Auth。
2.1 错误做法
在很多项目中,有些开发队伍为了图省事,客户对环境的掌控也不好,为了验证一个webservice,我们往往会采用以下这样的验证手法:
第一种:
http://xxxx.xxx.xxx/abc.wsdl?username=验证个头&password=验证个头
服务端拿到这个url把username,password用request.getParameter出来后,和数据库一匹配,验证。
第二种:
<Request xmlns="http://10.225.106.35"> <username>验证个头啊</username> <password>不要老是你个头你个头</password> <BusinessData>2007-01-01</BusinessData> </ Response >
服务端拿到后把这个soap request body中的<username>和<password>拿出来后和数据库一匹配,又验证了!
这两种做法,无疑是掩耳盗铃!!!(不要和我说业务实现是最主要的,等你的数据哪天没了,厂长经理的工资被篡改了,如果你愿意被客户做成东方不败,那你尽管去这样做就好了。)
2.2 正确的做法
通过上图我们可以看到,如果你的用户名和密码和服务端预设的用户名密码如果不匹配,你的“调用”,根本到达不了具体的Web Service,直接在Web Server端已经被打回来了,即你连wsdl都到达不了。
三、实际例子
3.1 Service端
我们编写一个Service端
org.sky.axis2.security.SimpleAuthService
package org.sky.axis2.security; public class SimpleAuthService { public double getTax(double salary) { // System.out.println("input salary=====" + salary); if (salary > 10000) { return 2000; } else if (salary > 1000 && salary <= 10000) { return 200; } else { return 0; } } }
service.xml文件的内容
<service name="SimpleAuthService"> <Description> Please Type your service description here </Description> <parameter name="ServiceClass" locked="false">org.sky.axis2.security.SimpleAuthService </parameter> <messageReceivers> <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" /> </messageReceivers> <actionMapping>urn:getTax</actionMapping> </service>
最重要的来了
修改web.xml文件,增加以