引用 :http://blog.csdn.net/lifetragedy/article/details/7844589
一、加密保護我們的web service傳輸
在上一天的教程中,我們講了一個簡單的基於” security-constraint”的以指定用戶名和密碼來保護一個Web Service以及如何用https對這個web service的通訊過程進行保護。雖然它用https來進行保護了,但是我們拋開https,這個web service之間傳輸的用戶名,密碼,數據都是明文的。
在我之間教程中曾經提到過,有一種黑客工具叫作sniffer,或者使用MIM-ATTACK(中間件攔截)的方式,也是可以把客戶端的流攔截住並且發往黑客主機的,這樣我們的用戶名和密碼就可以被黑客所獲取了。
因此,今天我們要講述的就是如何在web service傳輸時,使得這個用戶名和密碼以及相關數據也能被加密。
二、基本概念
我們先來看基本概念,這個基本概念將涉及到PKI的相關領域,請仔細看完這一章,要不然後面你將雲裏霧裏然後我勸你從頭來過,我將參照麻省理工大學的教程-RSA公司出版的“計算機加密與解密原理”,用最實際的例子和最簡化的語言把PKI中最重要的幾個概念給大家說清楚。
這次應該是我們第三次要求生成證書請求,證書,簽名了,挺折騰的!!!
不折騰你們不行,我要把大家折騰的蛋疼,這次折騰過後就徹底明白了。
被折騰着,痛苦着並最後快活着,好了我廢話又多了,下面開始。
2.1 加密解密的基本概念
我們的加密解密分兩種:
1) 對稱加密(Symmetric Cipher)
2) 非對稱加密(Asymmetric Cipher)
2.1.1 對稱加密
即採用一個密碼(密鑰)來對一串String進行解密,同樣這個密碼(密鑰)也能對被加密的密文進行解密,至始至終只有一個密碼(密鑰),因此它叫做對稱加密。
2.1.2 非對稱加密
這個是最重要的概念之一
我們知道,對稱加密只有一把密鑰(你可以把這個密鑰看成一個密碼)。而非對稱加密呢?它有2把密鑰,
l 一把我們稱爲私鑰即privatekey,一把私鑰可以對應着無數把公鑰,公鑰是可以“散播”的。
l 一把我們稱爲公鑰即publickey,一堆公鑰只能對應着僅有的一把私鑰,私鑰是絕對不可以“散播”的。
這兩把密鑰在產生時是被一起產生的,相當於同年同月生一樣,即生成私鑰時也伴隨着生成了公鑰。
下面公式來了:
公鑰加密,私鑰解密
大家試想一下哈,我有兩把鑰匙,一把是用來專門鎖門的(加密),一把是專門用來開門的(解密)。那麼我用來鎖門的那把key掉了,被其它人撿到了,要不要緊?大不了別人可以鎖我家的門。
但是,如果我用來開門的這麼key掉了?怎麼辦?被人撿到了人家就可以開我家的門進我家了。
因此,公鑰永遠被用來加密,可以有多把被多人持有,而私鑰永遠用來解密且只能主人自己擁有。
公鑰加密,私鑰解密!老老記住,這是永遠的公式,也是真理!
2.1.3 數字簽名
看了上面的“真理”即“公鑰加密,私鑰解密”後有人說了,我偏不信邪我就是要把它們倒過來,好好好!我們一起來看倒過來是什麼樣的,即成了“私鑰加密,公鑰解密”了。但話不能這樣說,真理是不容否定的,但倒過來不是也行?
行,行是行,不過這句話就不能這樣說了。
我們知道,公鑰是可以多把的,私鑰只有一把,因此:
1) 如果我們先把我們的明文用MD5或者SHA1這樣的雜湊算法做一個雜湊,得到一堆雜湊值我們稱它爲報文。
2) 然後呢我們拿着我們的私鑰來對着這個得到的雜湊碼不管它是MD5還是SHA1,做一個加密運算,就得到了一個“摘要”即Digest。
3) 然後我們把這個摘要和我們的明文一起發送給接收方。
4) 接收方首先用與發送方一樣的雜湊函數與接收到的原始明文中計算出這個雜湊計算,得到雜湊值即報文。
5) 接着再用發送方的公用密鑰來對這個報文附加的數字簽名進行解密,這樣,在接收方手上就會有兩樣東西了。
l 接收方用發送方的公鑰與所謂的原始明文運算得到的雜湊值或者稱爲報文也可稱爲摘要即digest。
l 接收方收到的由發送方發過來的摘要
6) 將這兩要東西,就是兩個摘要,它通常是如下的格式:
0a f5 b0 3f 38 6b 97 9c 08 62 9b 8b df d7 a0 c6 fe 00 12 08 |
把這兩個摘要一比較,完全一致我們就可以說:
從接收方發送來的摘要是出自某某某之手!爲什麼?
舉例來說:
因爲我們的公鑰和密鑰在產生時是一對的,Andy保留了私鑰,他把公鑰給了Forest。
If
Forest用這把公鑰和明文得到的摘要如果==Andy用私鑰和明文做了雜湊後發來的摘要
Then
這條消息一定是Andy發過來的。
除非Andy把他的私鑰交給了其它人並授權其它人代理他來做這個“私鑰簽證”
所以,我們得到另一條公式:
私鑰簽名,公鑰認證
這也是一條真理,不能違背,這條真理也被稱爲“數字簽名”,這邊的“認證”也可以稱爲“被信任”。
2.1.4 口令保護
我們的private key,public key如果一旦真的出現了private key被丟失的情況下怎麼辦?
不要緊,我們在private key上加一道鎖:
這下成了最右邊那個帶鎖的信封了,是不是,這個帶鎖的信封就是我們的鑰匙袋。
你要拿到我的私鑰就必須要先打開這個鑰匙帶,打開這個鑰匙帶你就必須再需要一把鑰匙。
一般這把鑰匙就是一個密碼,我們稱之爲“口令”。
來看如下的一個jks的生成來理解吧:
keytool -genkey -alias shnlap93client -keyalg RSA -keysize 1024 -dname "CN=shnlap93, OU=insurance, O=CTS, L=SH, S=SH, C=CN" -keypass bbbbbb -keystore shnlap93client.jks -storepass bbbbbb |
JKS文件就是“公鑰私鑰證書”在一起的一種證書格式。
一般證書如IE中的證書都只帶着公鑰(public key),而jsk是同時帶有公鑰和私鑰的證書。
因此,如果你要得到這對密鑰,你就必須要“解信封”,解開信封時你就要輸入密碼(口令),這邊的口令就是:keypass即bbbbbb六個小寫的b。
2.2 回過頭來看https與證書、公鑰、私鑰的關係
CA證書籤出一張服務器證書,在簽出籤書時CA使用自己的私鑰,簽完後怎麼叫作這張被籤的證書生效呢?因爲這張被籤的證書中含有着CA證書中的“公鑰”。
然後我們產生一個客戶端的證書,該客戶端的證書生成後我們把CA的公鑰也“燒”到客戶端的證書裏。
因此,我們有了下面這樣的一個關係(見第十三天教程中的3.3小節-需要爲我們的Axis2的調用客戶端也建立起https中的互信)。
這邊的客戶端jks文件(帶着RootCA),就是帶着RootCA的公鑰,因爲公鑰是可以多把的嗎,因此RootCA可以把自己的公鑰散播給其它人。
於是我們來套“私鑰簽名,公鑰認證”這個公式就得到了:
1) 因爲客戶端的jks文件的公鑰可以“認證”RootCA,即RootCA被客戶端信任。
2) 因爲服務端的ks文件也帶着RootCA的公鑰,可以“認證”RootCA,即RootCA可以被服務端信任。
3) 因此,客戶端可以信任服務端
2.3 使用jks文件來實現Server-Client間的“公鑰加密,私鑰解密”
上面說了,客戶端擁有RootCA的public key,服務端也擁有RootCA的public key,所以客戶端與服務端可以彼此間也建立起這條信任鏈。
但是,信任不代表它們可以實現“公鑰加密,私鑰解密”。
來看一個例子,這是今天的核心:
需求一、如果我們的客戶端對一個web service進行加密,然後傳到服務端進行解密。
對於需求一來說:
我們需要在客戶端用服務端的公鑰加密欲傳給服務端的消息,然後在服務端得到客戶端傳過來的加密消息後我們拿着服務端的私鑰進行解密。
需求二、服務端將返回的webservice的內容先用客戶端的公鑰加密後傳給客戶端,客戶端用自己的私鑰進行解密。
對於需求二來說:我們在服務端返回給客戶端消息之間先用客戶端的公鑰對消息進行加密,等消息傳到客戶端的時候,客戶端再拿着客戶端自己的私鑰進行解密。
是不是就可以滿足上述兩個需求了?
於是,根據上面的描述我們來做一件事,即:
l 把客戶端的公鑰燒到服務端的jks文件裏
l 把服務端的公鑰燒到客戶端的jks文件裏
即可達到上面兩個需求中的文字描述了,是不是?
一、使用Axis2Rampart實現Web Service安全規範
3.1 Axis2與Rampart
Web Service安全規範其實就是在講一套客戶端與服務端的webservice之間如何進行認證、加密的手段。在Axis2中,是以handler的模式來實現web service安全規範的。
在舊的Axis版本中,使用的是自己寫handler然後來實現客戶端與服務端之間的web service加密、認證。而到了Axis21.4版即後續版中,這個handler已經不需要我們手工寫了,Axis2爲我們提供了一個組件,這個組件叫rampart。
rampart是axis2實現ws-security的一個必須模塊。它基於wss4j來完成安全相關的任務,以下是rampart的工作原理:
因爲Rampart是基於Handler模式的,是對handler的一種封裝,它很像一個攔截器,因此有了Rampart我們可以在不需要改動客戶端、服務端的代碼的情況下只通過修改service端與client端的xml即可實現不同的web service安全規範,而且有了rampart我們只需要提供client端與server端的jks以及相關的“口令”和“用戶名(即jks的alias-別名)Rampart就可以自動爲我們進行:
加密;
解密;
認證;
而不需要我們再去書寫加密、解密、認證的底層API了,夠方便吧。
3.2 動手來做例子
需求:
實現客戶端訪問一個webservice,彼此間只通過http因此需要對客戶端傳給服務端的message進行加密,服務端得到客戶端傳來的加密的message後解密並把要返回給客戶端的消息進行加密返回給客戶端。客戶端得到服務端返回後的被加密的消息後進行解密,並顯示在客戶端。
3.2.1 搭建環境
請下載Rampart1.4(http://axis.apache.org/axis2/java/rampart/download.html)。
解壓後爲下面這樣的目錄結構:
l 把”modules”裏的兩個mar拷入你工程的WEB-INF\modules目錄下;
l 把lib目錄下的jar拷入你工程所在的WEB-INF\lib目錄下並加載入eclipse的classpath路徑中去;
開始實現我們的web service。
3.2.2 Service端
1)org.sky.axis2.security. MyRampartService
package org.sky.axis2.security;
import javax.xml.stream.XMLStreamException; import org.apache.axiom.om.OMElement;
public class MyRampartService { public String rampartMethod(String userName) throws XMLStreamException { return "hello: " + userName; } } |
2)service.xml文件
<service name="MyRampartService"> <description>test rampart service</description> <operation name="rampartMethod"> <messageReceiver class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" /> </operation> <parameter name="ServiceClass" locked="false">org.sky.axis2.security.MyRampartService </parameter> <module ref="rampart" /> <parameter name="InflowSecurity"> <action> <items>Encrypt</items> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <decryptionPropFile>service.properties</decryptionPropFile> </action> </parameter> <parameter name="OutflowSecurity"> <action> <items>Encrypt</items> <encryptionUser>shnlap93client</encryptionUser> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <encryptionPropFile>service.properties</encryptionPropFile> </action> </parameter> </service> |
通過上面的描述我們可以看到,這個Rampart的Service需要對兩個流即:流出(InflowSecurity)與流進( OutflowSecurity)進行攔截。
l InflowSecurity時
即client端使用service端的公鑰加密後提交上來的數據,我們在In時需要調用service端的私鑰進行解密,因此:
<action> <items>Encrypt</items> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <decryptionPropFile>service.properties</decryptionPropFile> </action> |
它使用一個實現了PasswordCallBack接口的類來進行調用service端的private key進行解密。
前面我們說過了,由於key都由口令保護着:
因此我們先來看這個” org.sky.axis2.security.RampartPasswordCB”類吧:
package org.sky.axis2.security; import Java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSPasswordCallback;
public class RampartPasswordCB implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i]; String id = pwcb.getIdentifer(); System.out.println("id====" + id); if ("shnlap93client".equals(id)) { pwcb.setPassword("bbbbbb"); } else if ("shnlap93server".equals(id)) { pwcb.setPassword("aaaaaa"); } else { System.out.println("Your are not a authorized user"); throw new UnsupportedCallbackException(callbacks[i], "Your are not a authorized user"); } } }
} |
要調用一個jks文件的內容需要知道兩大元素即:
1. 我們先要知道這個jks的Alias;
2. 我們要知道這個jks的保護口令;
比如說我們查看一個test.jks文件的內容因該用如下命令:
keytool –v –list–keystore test.jks
然後回車,此時console會提示我們輸入相關的密碼即口令,然後我們就可以看到這個jks文件的輸出了。
注意:
Jks文件的Alias名必須小寫。
因此我們回過頭來看上面的這個類
if ("shnlap93client".equals(id)) { pwcb.setPassword("bbbbbb"); } else if ("shnlap93server".equals(id)) { pwcb.setPassword("aaaaaa"); } else { System.out.println("Your are not a authorized user"); throw new UnsupportedCallbackException(callbacks[i], "Your are not a authorized user"); } |
由其是這一段,它就代表着,我們在解密時調用service端的jks的私鑰,要調用這個私鑰我們必須輸入:
Jks的alias與jks的key的保護口令。
這個類寫完後請放着,我們在書寫客戶端時將使用相同的類(一點代碼都不需要修改)。
InflowSecurity講完了,我們繼續看下去,來看這個OutflowSecurity
l OutflowSecurity時
流出時即Service端將要返回給Client端的內容加密然後輸出,因此OutflowSecurity裏做的應該是加密,對吧?
<parameter name="OutflowSecurity"> <action> <items>Encrypt</items> <encryptionUser>shnlap93client</encryptionUser> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <encryptionPropFile>service.properties</encryptionPropFile> </action> </parameter> |
加密用的是client端的公鑰,那麼Client的公鑰也需要輸入jks的alias,那麼客戶端公鑰的alias就是這個<encryptionUser>shnlap93client</encryptionUser>。
3)service.properties文件
最後來看這個service.properties文件:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=aaaaaa org.apache.ws.security.crypto.merlin.file=shnlap93.jks |
它位於如下目錄結構:
這個文件裏描述的就是Service端解密時需要使用的private key的alias與口令。
3.2.3 編寫client端前的準備
在編寫client端前,我們需要生成service端與client端的兩對密鑰,對吧?我們來看下面的表格:
|
Alias |
Password |
File Name |
Service端 |
shnlap93server |
aaaaaa |
shnlap93.jks |
Client端 |
Shnlap93client |
bbbbbb |
shnlap93client.jks |
全部爲小寫的哈!!!記住!
還記得我們前面已經做過幾次jks與證書了?
第一次:
爲tomcat的ssl我們生成了一個自籤的CA,把CA放到了我們的IE的根信任域,然後生成了一個服務端的證書,並且用CA對這張證書進行簽名,然後把生成的服務端的證書導成了jks,這個jks給了tomcat的server.xml進行配置https時用。相關命令如下:
生成CA的KEY: openssl genrsa -des3 -out ca.key 1024 從CA的KEY導出自籤的CA證書: openssl req -new -x509 -key catest.key -out catest.crt 生成服務端的jks: keytool -genkey -alias shnlap93server -keyalg RSA -keysize 1024 -dname "CN=shnlap93.cts.com, OU=insurance, O=CTS, L=SH, S=SH, C=CN" -keypass aaaaaa -keystore shnlap93.jks -storepass aaaaaa 通過服務端的jks生成證書請求: keytool -certreq -alias shnlap93server -sigalg "MD5withRSA" -file shnlap93.csr -keypass aaaaaa -keystore shnlap93.jks -storepass aaaaaa 用CA對服務端的證書請求進行簽名並形成服務端的證書: openssl x509 -req -in shnlap93.csr -out shnlap93.crt -CA ca.crt -CAkey ca.key -days 3650 -CAcreateserial -sha1 -trustout -CA ca.crt -CAkey ca.key -days 3650 -CAserial ca.srl -sha1 –trustout 先將CA導入服務端的jks的信任域即:trustcacerts中去: keytool -import -alias rootca -trustcacerts -file ca.crt -keystore shnlap93.jks -storepass aaaaaa 再把被CA簽了名的正式證書導入服務端的jks裏 keytool -import -alias shnlap93server -file shnlap93.crt -keystore shnlap93.jks -storepass aaaaaa |
第二次:
爲了使得我們的Java應用程序也能和tomcat之間形成https的連接,我們生成了一個client端的jks,然後把CA的公鑰導入了我們的client端的jks的信任域裏即:trustcacert中,使得我們的client端與server端通過共同信任同一個CA的公鑰而達成三角互信關係
相關命令如下:
生成客戶端的jks文件: keytool -genkey -alias shnlap93client -keyalg RSA -keysize 1024 -dname "CN=shnlap93, OU=insurance, O=CTS, L=SH, S=SH, C=CN" -keypassbbbbbb -keystore client.jks -storepassbbbbbb 將CA導入客戶端的信任域即trustcacerts中去: keytool -import -alias rootca -trustcacerts -file ca.crt -keystore shnlap93client.jks -storepassbbbbbb |
第三次:
就是這次,我們需要把
客戶端的公鑰導入服務端的jks,使得服務端的jks文件不僅有自己的公鑰與私鑰同時還帶着客戶端的公鑰,服務端的這個jks給服務端用。
服務端的公鑰導入客戶端的jks,使得客戶端的jks文件不僅有自己的公鑰與私鑰同時還帶着服務端的公鑰,客戶端的這個jks給客戶端用。
相關命令如下:
第一步:
先把客戶端的jks文件導成crt,jks導成crt後就會自動把jks裏的public key帶入到這個crt文件,因此也可以把jks導成crt看成是public key的導出。
第二步:
再把服務端的jks文件導成crt
第三步:
兩個public key都有了,然後互導!!
先將服務端的公鑰導入客戶端的jks文件裏,由於此時要對client端的jks文件內容進行修改,因此係統會提示輸入密碼,這個密碼就是client端的jks文件的口令即:bbbbbb六個b。
再將客戶端的公鑰導入服務端的jks文件裏,由於此時要對server端的jks文件內容進行修改,因此係統會提示輸入密碼,這個密碼就是server端的jks文件的口令即:aaaaaa六個a。
好了,兩個jks文件shnlap93.jks與shnlap93client.jks文件都有了,把shnlap93.jks文件放入工程的src目錄下使得工程在編譯時會把這個shnlap93.jks編譯進入我們的運行時的classpath
然後下面開始我們來編寫我們的client端了。
3.2.4 編寫client端
我們新建一個eclipse工程,一般Java工程即可。
工程結構如下:
l 把Rampart1.4中的modules目錄裏的.mar文件都拷入client工程的modules目錄下;
l 把Rampart1.4中的lib目錄裏的jar文件與axis2的lib目錄下的jar都拷入client工程的lib目錄下並加載入classpath;
l 把我們在3.2.3小節中生成的client端的jks文件即shnlap93client.jks文件放入client 工程的src目錄下。
l 把我們在3.2.2小節中生成的” org.sky.axis2.security.RampartPasswordCB”文件也拷入client工程。
1)org.sky.axis2.security. MyRampartServiceClient
package org.sky.axis2.security; import javax.xml.namespace.QName;
import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.client.Options; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.ConfigurationContextFactory;
public class MyRampartServiceClient {
private static EndpointReference targetEPR = new EndpointReference( "http://localhost:8080/Axis2Service/services/MyRampartService");
private String getAxis2ConfPath() { StringBuilder confPath = new StringBuilder(); confPath.append(this.getClass().getResource("/").getPath()); confPath.append("repository"); return confPath.toString(); }
private String getAxis2ConfFilePath() { String confFilePath = ""; confFilePath = getAxis2ConfPath() + "/axis2.xml"; return confFilePath;
}
public void testMyRampartService() { Options options = new Options(); options.setAction("urn:rampartMethod"); options.setTo(targetEPR); ServiceClient sender = null; String confFilePath = ""; String confPath = ""; try { confPath = this.getAxis2ConfPath(); confFilePath = getAxis2ConfFilePath(); System.out.println("confPath======" + confPath); System.out.println("confFilePath====" + confFilePath); ConfigurationContext configContext = ConfigurationContextFactory .createConfigurationContextFromFileSystem(confPath, confFilePath); sender = new ServiceClient(configContext, null); sender.setOptions(options);
OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "http://security.axis2.sky.org", ""); OMElement callMethod = fac.createOMElement("rampartMethod", omNs); OMElement nameEle = fac.createOMElement("name", omNs); nameEle.setText("Wang Clare"); callMethod.addChild(nameEle); OMElement response = sender.sendReceive(callMethod); System.out.println("response====>" + response); System.out.println(response.getFirstElement().getText()); } catch (Exception e) { e.printStackTrace(); } finally { if (sender != null) sender.disengageModule("addressing"); try { sender.cleanup(); } catch (Exception e) { } } }
public static void main(String[] args) { MyRampartServiceClient rampartServiceClient = new MyRampartServiceClient(); rampartServiceClient.testMyRampartService();
}
} |
這是一個標準的普通的web service訪問客戶端,沒啥花頭,唯一需要注意的就是:
ConfigurationContext configContext = ConfigurationContextFactory .createConfigurationContextFromFileSystem(confPath, confFilePath); sender = new ServiceClient(configContext, null); |
這個configContext需要兩個參數:
第一個參數指向:工程的src目錄下的repository文件夾;
第二個參數指向:工程的src目錄下的repository文件夾內的axis2.xml;
2)工程的src\repository\axis2.xml文件
這個文件可以直接從axis2下載解壓包中的conf目錄下的axis2.xml文件的內容拷貝過來,拷貝過來後在裏面添加如下內容(紅色加粗的部分爲我們手工添加的內容):
<axisconfig name="AxisJava2.0">
<module ref="rampart" /> <parameter name="OutflowSecurity"> <action> <items>Encrypt</items> <encryptionUser>shnlap93server</encryptionUser> <encryptionPropFile>client.properties</encryptionPropFile> </action> </parameter>
<parameter name="InflowSecurity"> <action> <items>Encrypt</items> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <decryptionPropFile>client.properties</decryptionPropFile> </action> </parameter> |
有了前面service.xml文件中的講述,這個內容因該不難看懂了吧?
它無非就是:
l 在In時,需要把從服務端用客戶端的公鑰加密後的數據,在客戶端用客戶端的私鑰進行解密;
l 在Out時,需要用服務端的公鑰對數據進行加密再傳給服務端。
3) client.properties文件
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=bbbbbb org.apache.ws.security.crypto.merlin.file=shnlap93client.jks |
它和service端的service.properties文件內容一樣,是對client 端的私鑰即shnlap93client.jks的口令與相關的alias的描述。
然後我們把service端佈署入tomcat並啓動得到我們的Web Service
我們先試着用SOAP UI來調用:
看到右邊的輸出沒?不成功,爲什麼?
WSDoAllReceiver: Incoming message does not contain requiredSecurity header
我們的Web Service已經是用戶名和密碼保護並且我們的request和response都必須是加密的了。
現在我們來在eclipse裏運行我們的客戶端:
看到輸出沒?調用成功。
四、換一種Web Service Security規範來試試同樣的例子
前面在3.1小節中我們說過了:
Rampart是攔截器原理,因此有了Rampart我們可以在不需要改動客戶端、服務端的代碼的情況下只通過修改service端與client端的xml即可實現不同的web service安全規範
我們前面這個例子用的是” Encrypting messages”方式。
我們現在來換成另一種更安全的叫” Sign and encrypt messages”的方式來對我們的web service的服務端與客戶端進行安全傳輸:
4.1 換service端的配置
service.xml文件
<module ref="rampart" /> <parameter name="InflowSecurity"> <action> <items>Timestamp Signature</items> <signaturePropFile>service.properties</signaturePropFile> </action> </parameter>
<parameter name="OutflowSecurity"> <action> <items>Timestamp Signature</items> <user>shnlap93server</user> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <signaturePropFile>service.properties</signaturePropFile> <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier> </action> </parameter> |
4.2 換client端的配置
axis2.xml文件
<module ref="rampart" /> <parameter name="OutflowSecurity"> <action> <items>Timestamp Signature</items> <user>shnlap93client</user> <signaturePropFile>client.properties</signaturePropFile> <passwordCallbackClass>org.sky.axis2.security.RampartPasswordCB</passwordCallbackClass> <signatureKeyIdentifier>DirectReference</signatureKeyIdentifier> </action> </parameter> <parameter name="InflowSecurity"> <action> <items>Timestamp Signature</items> <signaturePropFile>client.properties</signaturePropFile> </action> </parameter> |
好了,除這兩個xml配置文件中的內容換一下,其它的代碼,properties,jks文件都保持不動,再重新來運行我們的client端的程序:
成功,真棒!!!結束今天的教程,結束Axis2之旅。
有了這5天的Axis2教程,已經將Axis2的基本知識和概念介紹給了大家,大家通過這5天的學習再結合Axis2自帶的Sample相信可以完全掌握Axis2了。