16.7.3 对SOAP报文进行数字签名
使用用户名/密码虽然可以验证SOAP请求报文发送者的身份实现授权访问,但是服务端却无法保证报文在传输过程中没有被篡改——黑客可以截取使用了UsernameToken的SOAP报文并在篡改后再发送给服务端,就会使SOAP报文的完整性遭受破坏。
此外,仅使用UsernameToken的SOAP,客户端用户可以抵赖自己的操作行为,因为黑客确实可以通过一些手段(如键盘监听、暴力**等)获取用户的密码。
而
数字签名则可以解决以上的问题,保证交易的完整性和不可抵赖性。客户端通过私钥对SOAP报文进行数字签名,由于私钥只为个人拥有,因此不可抵赖性得到了
保证。数字签名其实是使用私钥对报文的摘要进行加密,只有报文在传输过程中不被篡改,接收端在进行数字签名验证时才可能成功,因此完整性又得到了保证。
下面,我们在客户端对请求SOAP进行数字签名,而服务端验证客户端签名的合法性。客户端使用client私钥进行数字签名,服务端使用client的数字证书(包含client的公钥)验证客户端的签名。
服务端
服务端在验证客户端的签名时,必须访问serverStore.jks中的client数字证书,所以需要进行相应的配置,如代码清单16-14所示:
insecurity_sign.properties定义了serverStore.jks的位置 以及访问密码,WSS4J使用org.apache.ws.security.components.crypto.Merlin类作为 SecurityProvider。insecurity_sign.properties的内容如下所示:
客户端
客户端必须通过注册OutHandler使用私钥对SOAP报文进行数字签名。客户端的私钥别名为client,存储在clientStore.jks的**库中。访问**库和私钥都必须提供密码,因此必须进行相应的设置。
和用户名/密码进行身份认证相似,在进行数字签名时,也需要提供用户名和密码,不过两者的用途是不一 样的,后者的用户名为**库中**对的别名,密码为私钥的访问**。③处的client为clientStore.jks**库中客户端**对的别名,私 钥访问密码通过PasswordHandler获取,如代码清单16-16所示:
客户端的私钥位于clientStore.jks中,访问clientStore.jks的配置信息通过outsecurity_ sign.properties属性文件进行描述:
运行BbtForumServiceSignClient后,查看SOAP请求报文,用户将看到报文 头拥有一个<ds:Signature>元素,包含了签名信 息<ds:SignedInfo>、<ds:SignatureValue>、<ds:KeyInfo>等元素,它 们分别代表签名信息、签名值以及签名所用**的信息:
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/ "> <SOAP:Header> <wsse:Security> <ds:Signature> <ds:SignedInfo>…<ds:SignedInfo> <ds:SignatureValue>…</ ds:SignatureValue> <ds:KeyInfo>…</ds:KeyInfo > </ds:Signature> </wsse:Security> </SOAP:Header> <SOAP:Body Id='Body'> … </SOAP:Body> </SOAP:Envelope>