用axis发布web services (五)
2007-01-17 08:53 P.M.
Web 服务安全性相关技术和开发工具
Web 服务安全性规范是一套可以帮助 Web 服务开发者保证 SOAP 消息交换的安全的机制。WS-Security 特别描述了对现有的 SOAP 消息传递的增强,从而通过对 SOAP 消息应用消息完整性、消息机密性和单消息认证提供了保护级别。这些基本机制可以通过各种方式联合,以适应构建使用多种加密技术的多种安全性模型。
围绕Web服务的安全,有很多相关的技术,比如WS-Security,WS-Trace等,另外,还有以下相关技术:
XML Digital Signature(XML数字签名)
XML Encryption (XML加密)
XKMS (XML Key Management Specification)
XACML (eXtensible Access Control Markup Language)
SAML (Secure Assertion Markup Language)
ebXML Message Service Security
Identity Management & Liberty Project
由于本文是一个实例性文章,故不对WS-Security做详细的探讨,你可以在develperWorks Web 服务安全专题找到许多相关资料(见参考资料)。
Trust Services Integration Kit提供了一个WS-Security实现。你可以从http://www.xmltrustcenter.org获得相关库文件,分别是wssecurity.jar和tsik.jar。wssecurity.jar中包含一个WSSecurity类,可以使用它来对XML进行数字签名和验证,加密与解密。
下面我们使用WS-Security来对SOAP消息进行数字签名,然后再进行验证。
SOAP消息的签名和验证
使用WSSecurity对SOAP消息数字签名
在对SOAP消息进行签名前,首先生成一个keystore。keystore包含了进行数字签名所需要的身份信息。通过以下批处理脚本来创建keystore:
例程1 创建keystore(server.keystore)
set SERVER_DN="CN=hellking-Server, OU=huayuan, O=huayuan, L=BEIJINGC, S=BEIJING, C=CN"
set KS_PASS=-storepass changeit
set KS_TYPE=-storetype JKS
set KEYINFO=-keyalg RSA
#生成服务器端keystore。
keytool -genkey -dname %SERVER_DN% %KS_PASS% %KS_TYPE% -keystore
server.keystore %KEYINFO% -keypass changeit
SignAndVerifySoap类中包含了一个对XML进行签名的方法,它就是sign(),这个方法将对SOAP消息进行签名,然后输出和WS-Security兼容的SOAP消息。下面我们看具体代码。
例程2 对SOAP消息签名
package com.hellking.study.webservice;
import com.verisign.messaging.WSSecurity;
...
public class SignAndVerifySoap {
final String KEY_STORE = "server.keystore";
final String SOTE_PASS = "changeit";
final String KEY_ALIAS="mykey";
final String TARGET_FILE="signed.xml";//签名后的SOAP消息
final String SOURE_FILE="source.xml";//签名前的SOAP消息
final String KEY_TYPE="JKS";
/**
*对xml进行签名
*/
public void sign()
{
try
{
System.out.println("开始对SOAP消息进行签名,使用的密匙库:" + KEY_STORE + "\n");
// 获得私有key和相关证书,请参考JAVA安全编程相关书籍
FileInputStream fileInputStream = new FileInputStream(KEY_STORE);
System.out.println(java.security.KeyStore.getDefaultType());
java.security.KeyStore store = java.security.KeyStore.getInstance(KEY_TYPE);
store.load(fileInputStream, SOTE_PASS.toCharArray());
PrivateKey key = (PrivateKey)store.getKey(KEY_ALIAS, SOTE_PASS.toCharArray());
X509Certificate certification = (X509Certificate)store.getCertificate(KEY_ALIAS);
// 读取XML源文件到文档中
Document source = readFile(SOURE_FILE);
SigningKey signingKey = SigningKeyFactory.makeSigningKey(key);
KeyInfo keyInfo = new KeyInfo();
keyInfo.setCertificate(certification);
WSSecurity wsSecurity = new WSSecurity();
wsSecurity.setPreferredNamespace("http://schemas.xmlsoap.org/ws/2003/06/secext");
//对SOAP消息进行签名
wsSecurity.sign(source, signingKey, keyInfo);
// 保存签名后的SOAP消息
writeFile(source, new FileOutputStream(TARGET_FILE));
System.out.println("把签名后的文件写入: " + TARGET_FILE + ",请查看结果!");
}
catch(Exception e)
{
e.printStackTrace();
}
}
在执行此程序前,请把wssecurity.jar、source.xml和tsik.jar设置到类路径环境变量中。签名前的SOAP为:
例程3 签名前的SOAP消息(source.xml)
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getTax soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://hellking.webservices.com/">
<op1 xsi:type="xsd:double">5000.0</op1>
</ns1:getTax>
</soapenv:Body>
</soapenv:Envelope>
签名后的SOAP消息如例程4所示。
例程4 签名后的SOAP消息(signed.xml)
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext">
<wsse:BinarySecurityToken EncodingType="wsse:Base64Binary"
ValueType="wsse:X509v3" wsu:Id="wsse-ee805a80-cd95-11d8-9cf9-fd6213c0f8be"
xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">MIICUjCCAbsCBEDB0GIwDQYJKoZIhvcNAQE…VkTkPw==
</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#wsse-ee5308f0-cd95-11d8-9cf9-fd6213c0f8be">
<ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ZjRVnI2g7kcX0h9r4JtiltpYQPA=</ds:DigestValue></ds:Reference>
<ds:Reference URI="#wsse-ee4e4e00-cd95-11d8-9cf9-fd6213c0f8be">
<ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>moZ0d+8mH1kfNw0VEK39V0Td9EM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>fPpYrf0uNP8W2XVVIQNc3OQt2Wn90M/0uJ0dDZTNRR0NxBBBX36wSXt7NfI5Fmh4ru44Wk34EGI7mqMAE5O0
/wtIlFRJt3zAvA6k3nhgcYj6tn/9kZwwxh1RkFTfTX9xdQ6Xn+P6m+YBm1YEEcTWkJd7XcxdyDEns2kYOhONx1U=
</ds:SignatureValue>
<ds:KeyInfo><wsse:SecurityTokenReference>
<wsse:Reference URI="#wsse-ee805a80-cd95-11d8-9cf9-fd6213c0f8be"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature></wsse:Security>
<wsu:Timestamp xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
<wsu:Created wsu:Id="wsse-ee4e4e00-cd95-11d8-9cf9-fd6213c0f8be">2004-07-04T08:41:23Z</wsu:Created>
</wsu:Timestamp></soapenv:Header>
<soapenv:Body wsu:Id="wsse-ee5308f0-cd95-11d8-9cf9-fd6213c0f8be"
xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
<ns1:getTax soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://hellking.webservices.com/">
<op1 xsi:type="xsd:double">5000.0</op1>
</ns1:getTax>
</soapenv:Body>
</soapenv:Envelope>
签名后的SOAP消息中,头部包含了签名信息以及验证SOAP消息所需要的key。<SignedInfo> </SignedInfo> 描述了已签署的消息内容。<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 指出了签名算法(Signature Method Algorithm)。这个算法被用来将规范算法的输出转换成签名值(Signature Value)。Key Info 元素包含的部分就是数字证书本身。
对签名的SOAP消息进行验证
对SOAP消息进行验证就是使用keystore的信息生成TrustVerifier对象,然后调用WSSecurity的verify方法进行验证。
例程5 验证签名后的SOAP消息
/**
*验证已经签名的SOAP消息
*/
public void verify()
{
try
{
System.out.println("开始检验SOAP消息,使用的密匙库:" + KEY_STORE + "\n");
// 获得私有key和相关证书,请参考JAVA安全编程相关书籍
FileInputStream fileInputStream = new FileInputStream(KEY_STORE);
java.security.KeyStore store = java.security.KeyStore.getInstance(KEY_TYPE);
store.load(fileInputStream, SOTE_PASS.toCharArray());
// 读取XML源文件到文档中
Document source = readFile(TARGET_FILE);
org.xmltrustcenter.verifier.TrustVerifier verifier =
new org.xmltrustcenter.verifier.X509TrustVerifier(store);
WSSecurity wsSecurity = new WSSecurity();
com.verisign.messaging.MessageValidity[] resa =
wsSecurity.verify(source,verifier,null,null);
System.out.println("检验结果:");
for (int len = 0; len < resa.length; len++){
System.out.println("result[" + len + "] = " + (resa[len].isValid()?"验证通过":"验证不通过"));
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
执行SignAndVerifySoap的verify方法,可以看到类似以下的结果。
图1 对SOAP消息进行验证
回页首
在AXIS下实现WS-Security的应用框架
待开发的应用开发框架基于Handler实现,将达到以下目标:此框架基于JAX-RPC环境下实现WS-Security应用,它可以部署到任何需要实现WS-Security的axis环境下的Web服务应用中,同时具体的应用程序不做任何编码修改。
由于此基于Handler实现,我们有必要回顾一下Handler的一些基础知识。
SOAP消息Handler能够访问代表RPC请求或者响应的SOAP消息。在JAX-RPC技术中,SOAP消息Handler可以部署在服务端,也可以在客户端使用。
SOAP消息Handler非常像Servlet技术中的Filter,它们共同的特点是请求发送到目标前,Handler/Filter可以截取这些请求,并对请求做一些处理,从而达到一些辅助的功能。多个Handler可以组成一个Handler链,链上的每个Handler都完成某个特定的任务。比如有的Handler进行权限验证,有的Handler进行日志处理等。关于Handler更详细的介绍,请参考本系列文章《 J2EE Web服务开发系列之六: 使用Handler来增强Web服务的功能》。
实现原理
图2是此例子具体实现原理图。
图2 Handler结合WSSecurity实现Web服务安全的工作原理
处理流程如下:
1、 客户端(WSSClient)发出调用Web服务请求;
2、 客户端Handler(WSSecurityClientHandler)截获请求的SOAP消息;
3、 客户端Handler对截获的SOAP消息进行数字签名(使用client.keystore作为签名依据);
4、 客户端Handler对签名后的SOAP消息进行加密(使用RSA算法加密);
5、 被加密的SOAP消息通过互联网传送到目标Web服务端口;
6、 服务器端Handler(WSSecurityServerHandler)截获加密的SOAP消息;
7、 服务器端Handler对加密的SOAP消息进行解密;
8、 服务器端Handler对SOAP消息进行身份验证(server.truststore包含了所信任的身份信息),如果验证不通过,将抛出异常;
9、 服务器端Handler删除被解密后的SOAP消息中与WS-Security相关的元素;
10、 解密后的原始SOAP消息被发送到目标Web服务端口(如TaxService);
11、 目标Web服务对Web服务请求进行处理,然后返回响应的SOAP消息;
12、 服务器端Handler截获响应的SOAP消息;
13、 服务器端Handler对截获的SOAP消息进行数字签名(使用server.keystore作为签名依据);
14、 服务器端Handler对签名后的SOAP消息进行加密(使用RSA算法加密);
15、 被加密的SOAP消息通过互联网传送到目客户端;
16、 客户端Handler截获加密的SOAP消息;
17、 客户端Handler对加密的SOAP消息进行解密;
18、 客户端Handler对SOAP消息进行身份验证(client.truststore包含了所信任的身份信息),如果验证不通过,将抛出异常;
19、 客户端Handler删除被解密后的SOAP消息中与WS-Security相关的元素;
20、 被解密后的SOAP消息发送到目标客户端,客户端输出调用结果。
从上面可以看出,在一个SOAP调用回合中,要对SOAP消息进行四次处理。基本上都是"签名'加密'解密'验证"的过程。
创建相关密匙库
客户端和服务端都有相关的密匙库,其中:
client.keystore:客户端自身的身份信息;
client.truststore:客户端所信任的身份信息,在此例中也就是包含了服务器的身份信息;
server.keystore:服务器自身的身份信息;
server.truststore:服务器所信任的身份信息(即客户端身份信息)。
你可以使用以下的批处理脚本创建上面四个密匙库。
例程6 创建相关密匙库(gen-cer-store.bat)
set SERVER_DN="CN=hellking-Server, OU=huayuan, O=huayuan, L=BEIJINGC, S=BEIJING, C=CN"
set CLIENT_DN="CN=hellking-Client, OU=tsinghua, O=tsinghua, L=BEIJING, S=BEIJING, C=CN"
set KS_PASS=-storepass changeit
set KEYINFO=-keyalg RSA
#生成server.keystore。
keytool -genkey -dname %SERVER_DN% %KS_PASS% -keystore server.keystore %KEYINFO% -keypass changeit
#从server.keystore导出数字证书。
keytool -export -file test_axis.cer %KS_PASS% -keystore server.keystore
#从服务器的数字证书导出到客户端信任的truststore中。
keytool -import -file test_axis.cer %KS_PASS% -keystore client.truststore -alias serverkey -noprompt
#生成client.keystore。
keytool -genkey -dname %CLIENT_DN% %KS_PASS% -keystore client.keystore %KEYINFO% -keypass changeit
#从client.keystore导出数字证书。
keytool -export -file test_axis.cer %KS_PASS% -keystore client.keystore
#从客户端的数字证书导出到服务器信任的truststore中。
keytool -import -file test_axis.cer %KS_PASS% -keystore server.truststore -alias clientkey -noprompt
#end
2007-01-17 08:53 P.M.
Web 服务安全性相关技术和开发工具
Web 服务安全性规范是一套可以帮助 Web 服务开发者保证 SOAP 消息交换的安全的机制。WS-Security 特别描述了对现有的 SOAP 消息传递的增强,从而通过对 SOAP 消息应用消息完整性、消息机密性和单消息认证提供了保护级别。这些基本机制可以通过各种方式联合,以适应构建使用多种加密技术的多种安全性模型。
围绕Web服务的安全,有很多相关的技术,比如WS-Security,WS-Trace等,另外,还有以下相关技术:
XML Digital Signature(XML数字签名)
XML Encryption (XML加密)
XKMS (XML Key Management Specification)
XACML (eXtensible Access Control Markup Language)
SAML (Secure Assertion Markup Language)
ebXML Message Service Security
Identity Management & Liberty Project
由于本文是一个实例性文章,故不对WS-Security做详细的探讨,你可以在develperWorks Web 服务安全专题找到许多相关资料(见参考资料)。
Trust Services Integration Kit提供了一个WS-Security实现。你可以从http://www.xmltrustcenter.org获得相关库文件,分别是wssecurity.jar和tsik.jar。wssecurity.jar中包含一个WSSecurity类,可以使用它来对XML进行数字签名和验证,加密与解密。
下面我们使用WS-Security来对SOAP消息进行数字签名,然后再进行验证。
SOAP消息的签名和验证
使用WSSecurity对SOAP消息数字签名
在对SOAP消息进行签名前,首先生成一个keystore。keystore包含了进行数字签名所需要的身份信息。通过以下批处理脚本来创建keystore:
例程1 创建keystore(server.keystore)
set SERVER_DN="CN=hellking-Server, OU=huayuan, O=huayuan, L=BEIJINGC, S=BEIJING, C=CN"
set KS_PASS=-storepass changeit
set KS_TYPE=-storetype JKS
set KEYINFO=-keyalg RSA
#生成服务器端keystore。
keytool -genkey -dname %SERVER_DN% %KS_PASS% %KS_TYPE% -keystore
server.keystore %KEYINFO% -keypass changeit
SignAndVerifySoap类中包含了一个对XML进行签名的方法,它就是sign(),这个方法将对SOAP消息进行签名,然后输出和WS-Security兼容的SOAP消息。下面我们看具体代码。
例程2 对SOAP消息签名
package com.hellking.study.webservice;
import com.verisign.messaging.WSSecurity;
...
public class SignAndVerifySoap {
final String KEY_STORE = "server.keystore";
final String SOTE_PASS = "changeit";
final String KEY_ALIAS="mykey";
final String TARGET_FILE="signed.xml";//签名后的SOAP消息
final String SOURE_FILE="source.xml";//签名前的SOAP消息
final String KEY_TYPE="JKS";
/**
*对xml进行签名
*/
public void sign()
{
try
{
System.out.println("开始对SOAP消息进行签名,使用的密匙库:" + KEY_STORE + "\n");
// 获得私有key和相关证书,请参考JAVA安全编程相关书籍
FileInputStream fileInputStream = new FileInputStream(KEY_STORE);
System.out.println(java.security.KeyStore.getDefaultType());
java.security.KeyStore store = java.security.KeyStore.getInstance(KEY_TYPE);
store.load(fileInputStream, SOTE_PASS.toCharArray());
PrivateKey key = (PrivateKey)store.getKey(KEY_ALIAS, SOTE_PASS.toCharArray());
X509Certificate certification = (X509Certificate)store.getCertificate(KEY_ALIAS);
// 读取XML源文件到文档中
Document source = readFile(SOURE_FILE);
SigningKey signingKey = SigningKeyFactory.makeSigningKey(key);
KeyInfo keyInfo = new KeyInfo();
keyInfo.setCertificate(certification);
WSSecurity wsSecurity = new WSSecurity();
wsSecurity.setPreferredNamespace("http://schemas.xmlsoap.org/ws/2003/06/secext");
//对SOAP消息进行签名
wsSecurity.sign(source, signingKey, keyInfo);
// 保存签名后的SOAP消息
writeFile(source, new FileOutputStream(TARGET_FILE));
System.out.println("把签名后的文件写入: " + TARGET_FILE + ",请查看结果!");
}
catch(Exception e)
{
e.printStackTrace();
}
}
在执行此程序前,请把wssecurity.jar、source.xml和tsik.jar设置到类路径环境变量中。签名前的SOAP为:
例程3 签名前的SOAP消息(source.xml)
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getTax soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://hellking.webservices.com/">
<op1 xsi:type="xsd:double">5000.0</op1>
</ns1:getTax>
</soapenv:Body>
</soapenv:Envelope>
签名后的SOAP消息如例程4所示。
例程4 签名后的SOAP消息(signed.xml)
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext">
<wsse:BinarySecurityToken EncodingType="wsse:Base64Binary"
ValueType="wsse:X509v3" wsu:Id="wsse-ee805a80-cd95-11d8-9cf9-fd6213c0f8be"
xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">MIICUjCCAbsCBEDB0GIwDQYJKoZIhvcNAQE…VkTkPw==
</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#wsse-ee5308f0-cd95-11d8-9cf9-fd6213c0f8be">
<ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ZjRVnI2g7kcX0h9r4JtiltpYQPA=</ds:DigestValue></ds:Reference>
<ds:Reference URI="#wsse-ee4e4e00-cd95-11d8-9cf9-fd6213c0f8be">
<ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>moZ0d+8mH1kfNw0VEK39V0Td9EM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>fPpYrf0uNP8W2XVVIQNc3OQt2Wn90M/0uJ0dDZTNRR0NxBBBX36wSXt7NfI5Fmh4ru44Wk34EGI7mqMAE5O0
/wtIlFRJt3zAvA6k3nhgcYj6tn/9kZwwxh1RkFTfTX9xdQ6Xn+P6m+YBm1YEEcTWkJd7XcxdyDEns2kYOhONx1U=
</ds:SignatureValue>
<ds:KeyInfo><wsse:SecurityTokenReference>
<wsse:Reference URI="#wsse-ee805a80-cd95-11d8-9cf9-fd6213c0f8be"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature></wsse:Security>
<wsu:Timestamp xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
<wsu:Created wsu:Id="wsse-ee4e4e00-cd95-11d8-9cf9-fd6213c0f8be">2004-07-04T08:41:23Z</wsu:Created>
</wsu:Timestamp></soapenv:Header>
<soapenv:Body wsu:Id="wsse-ee5308f0-cd95-11d8-9cf9-fd6213c0f8be"
xmlns:wsu="http://schemas.xmlsoap.org/ws/2003/06/utility">
<ns1:getTax soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://hellking.webservices.com/">
<op1 xsi:type="xsd:double">5000.0</op1>
</ns1:getTax>
</soapenv:Body>
</soapenv:Envelope>
签名后的SOAP消息中,头部包含了签名信息以及验证SOAP消息所需要的key。<SignedInfo> </SignedInfo> 描述了已签署的消息内容。<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> 指出了签名算法(Signature Method Algorithm)。这个算法被用来将规范算法的输出转换成签名值(Signature Value)。Key Info 元素包含的部分就是数字证书本身。
对签名的SOAP消息进行验证
对SOAP消息进行验证就是使用keystore的信息生成TrustVerifier对象,然后调用WSSecurity的verify方法进行验证。
例程5 验证签名后的SOAP消息
/**
*验证已经签名的SOAP消息
*/
public void verify()
{
try
{
System.out.println("开始检验SOAP消息,使用的密匙库:" + KEY_STORE + "\n");
// 获得私有key和相关证书,请参考JAVA安全编程相关书籍
FileInputStream fileInputStream = new FileInputStream(KEY_STORE);
java.security.KeyStore store = java.security.KeyStore.getInstance(KEY_TYPE);
store.load(fileInputStream, SOTE_PASS.toCharArray());
// 读取XML源文件到文档中
Document source = readFile(TARGET_FILE);
org.xmltrustcenter.verifier.TrustVerifier verifier =
new org.xmltrustcenter.verifier.X509TrustVerifier(store);
WSSecurity wsSecurity = new WSSecurity();
com.verisign.messaging.MessageValidity[] resa =
wsSecurity.verify(source,verifier,null,null);
System.out.println("检验结果:");
for (int len = 0; len < resa.length; len++){
System.out.println("result[" + len + "] = " + (resa[len].isValid()?"验证通过":"验证不通过"));
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
执行SignAndVerifySoap的verify方法,可以看到类似以下的结果。
图1 对SOAP消息进行验证
回页首
在AXIS下实现WS-Security的应用框架
待开发的应用开发框架基于Handler实现,将达到以下目标:此框架基于JAX-RPC环境下实现WS-Security应用,它可以部署到任何需要实现WS-Security的axis环境下的Web服务应用中,同时具体的应用程序不做任何编码修改。
由于此基于Handler实现,我们有必要回顾一下Handler的一些基础知识。
SOAP消息Handler能够访问代表RPC请求或者响应的SOAP消息。在JAX-RPC技术中,SOAP消息Handler可以部署在服务端,也可以在客户端使用。
SOAP消息Handler非常像Servlet技术中的Filter,它们共同的特点是请求发送到目标前,Handler/Filter可以截取这些请求,并对请求做一些处理,从而达到一些辅助的功能。多个Handler可以组成一个Handler链,链上的每个Handler都完成某个特定的任务。比如有的Handler进行权限验证,有的Handler进行日志处理等。关于Handler更详细的介绍,请参考本系列文章《 J2EE Web服务开发系列之六: 使用Handler来增强Web服务的功能》。
实现原理
图2是此例子具体实现原理图。
图2 Handler结合WSSecurity实现Web服务安全的工作原理
处理流程如下:
1、 客户端(WSSClient)发出调用Web服务请求;
2、 客户端Handler(WSSecurityClientHandler)截获请求的SOAP消息;
3、 客户端Handler对截获的SOAP消息进行数字签名(使用client.keystore作为签名依据);
4、 客户端Handler对签名后的SOAP消息进行加密(使用RSA算法加密);
5、 被加密的SOAP消息通过互联网传送到目标Web服务端口;
6、 服务器端Handler(WSSecurityServerHandler)截获加密的SOAP消息;
7、 服务器端Handler对加密的SOAP消息进行解密;
8、 服务器端Handler对SOAP消息进行身份验证(server.truststore包含了所信任的身份信息),如果验证不通过,将抛出异常;
9、 服务器端Handler删除被解密后的SOAP消息中与WS-Security相关的元素;
10、 解密后的原始SOAP消息被发送到目标Web服务端口(如TaxService);
11、 目标Web服务对Web服务请求进行处理,然后返回响应的SOAP消息;
12、 服务器端Handler截获响应的SOAP消息;
13、 服务器端Handler对截获的SOAP消息进行数字签名(使用server.keystore作为签名依据);
14、 服务器端Handler对签名后的SOAP消息进行加密(使用RSA算法加密);
15、 被加密的SOAP消息通过互联网传送到目客户端;
16、 客户端Handler截获加密的SOAP消息;
17、 客户端Handler对加密的SOAP消息进行解密;
18、 客户端Handler对SOAP消息进行身份验证(client.truststore包含了所信任的身份信息),如果验证不通过,将抛出异常;
19、 客户端Handler删除被解密后的SOAP消息中与WS-Security相关的元素;
20、 被解密后的SOAP消息发送到目标客户端,客户端输出调用结果。
从上面可以看出,在一个SOAP调用回合中,要对SOAP消息进行四次处理。基本上都是"签名'加密'解密'验证"的过程。
创建相关密匙库
客户端和服务端都有相关的密匙库,其中:
client.keystore:客户端自身的身份信息;
client.truststore:客户端所信任的身份信息,在此例中也就是包含了服务器的身份信息;
server.keystore:服务器自身的身份信息;
server.truststore:服务器所信任的身份信息(即客户端身份信息)。
你可以使用以下的批处理脚本创建上面四个密匙库。
例程6 创建相关密匙库(gen-cer-store.bat)
set SERVER_DN="CN=hellking-Server, OU=huayuan, O=huayuan, L=BEIJINGC, S=BEIJING, C=CN"
set CLIENT_DN="CN=hellking-Client, OU=tsinghua, O=tsinghua, L=BEIJING, S=BEIJING, C=CN"
set KS_PASS=-storepass changeit
set KEYINFO=-keyalg RSA
#生成server.keystore。
keytool -genkey -dname %SERVER_DN% %KS_PASS% -keystore server.keystore %KEYINFO% -keypass changeit
#从server.keystore导出数字证书。
keytool -export -file test_axis.cer %KS_PASS% -keystore server.keystore
#从服务器的数字证书导出到客户端信任的truststore中。
keytool -import -file test_axis.cer %KS_PASS% -keystore client.truststore -alias serverkey -noprompt
#生成client.keystore。
keytool -genkey -dname %CLIENT_DN% %KS_PASS% -keystore client.keystore %KEYINFO% -keypass changeit
#从client.keystore导出数字证书。
keytool -export -file test_axis.cer %KS_PASS% -keystore client.keystore
#从客户端的数字证书导出到服务器信任的truststore中。
keytool -import -file test_axis.cer %KS_PASS% -keystore server.truststore -alias clientkey -noprompt
#end