本節摘要:本節主要介紹webservice的安全機制。
1.引言
俗話說,安全第一;
那么,我們軟件中是否有安全,安全是否重要呢?
sure,軟件開發中當然也有安全,安全顯得尤為重要。
本節,我們將一起來看看webservice的安全問題。
之前在前幾節中寫了webservice開發相關的知識,接下來幾節我會寫webservice安全相關的問題。
閑扯一點,
本來這部分在上個月就准備寫的,但是確實是太忙了,每天加班,晚上回到家都快十一點了,偶爾還要通宵去上線,周末還要去奮戰一天,實在是沒那個精力,乘着今天下班早點,就來寫寫了,寫博客也是我喜歡的事情嘛。
2.webservice安全機制分類
首先聲明,這里的分類不一定准確,只是我站在目前的高度,對能了解到的,能想到的做一個簡單的分類;再者,這里的分類都是站在代碼的角度來寫的,至於你說的防火牆、DMZ....這些都不在我的考慮范圍之內。
(1)對webservice發布的方法,方法名稱和參數不要使用望文生義的描述;
(2)對webservice發布的方法,在入參中增加一個或多個字符串序列;
這里的字符串可以要求必須滿足指定的格式,同時字符串可以再通過客戶端傳參數的時候加密,服務端解密;
(3)對webservice發布的方法,入參中加上用戶名和密碼,然后服務端通過數據庫校驗;
(4)對webservice發布的方法,通過handler/chain方式來實現驗證(用戶名&密碼校驗/IP地址校驗等);
(5)對webservice發布的方法,采用webservice的users.lst來進行驗證;
(6)對webservice發布的服務,通過servlet的Filter來實現驗證;
(7)對webservice傳輸過程中的數據進行加密;
(8)自己寫校驗框架來實現webservice的安全;
(9)其它方式......
各位大蝦,認為還有哪些比較好的方式,歡迎指出。
3.webservice安全實現
既然webservice的安全方式有那么多種,那么具體是怎么實現的呢?
接下來幾節,我會介紹webservice采用users.lst、chain、Filter實現webservice的方式;本節,就來介紹一下最簡單的,采用webservice自帶的users.lst的方式。
3.1開發一個基本的webservice
項目結構圖如下:
(1)服務端代碼:
HelloServiceImpl.java

1 package server.service; 2 3 public class HelloServiceImpl { 4 5 public String hello(String s) { 6 System.out.println("我是服務端......"); 7 System.out.println("方法的入參為:"+s); 8 return "hello," + s; 9 } 10 }
(2)服務端wsdd文件的配置
server-config.wsdd

<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <globalConfiguration> <parameter name="sendMultiRefs" value="true" /> <parameter name="disablePrettyXML" value="true" /> <parameter name="adminPassword" value="admin" /> <parameter name="attachments.Directory" value="D:\tomcat5\webapps\WebService\WEB-INF\attachments" /> <parameter name="dotNetSoapEncFix" value="true" /> <parameter name="enableNamespacePrefixOptimization" value="false" /> <parameter name="sendXMLDeclaration" value="true" /> <parameter name="sendXsiTypes" value="true" /> <parameter name="attachments.implementation" value="org.apache.axis.attachments.AttachmentsImpl" /> <requestFlow> <handler type="java:org.apache.axis.handlers.JWSHandler"> <parameter name="scope" value="session" /> </handler> <handler type="java:org.apache.axis.handlers.JWSHandler"> <parameter name="scope" value="request" /> <parameter name="extension" value=".jwr" /> </handler> </requestFlow> </globalConfiguration> <handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder" /> <handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper" /> <handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" /> <service name="AdminService" provider="java:MSG"> <parameter name="allowedMethods" value="AdminService" /> <parameter name="enableRemoteAdmin" value="false" /> <parameter name="className" value="org.apache.axis.utils.Admin" /> <namespace>http://xml.apache.org/axis/wsdd/</namespace> </service> <service name="Version" provider="java:RPC"> <parameter name="allowedMethods" value="getVersion" /> <parameter name="className" value="org.apache.axis.Version" /> </service> <transport name="http"> <requestFlow> <handler type="URLMapper" /> <handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" /> </requestFlow> <parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" /> <parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" /> <parameter name="qs.list" value="org.apache.axis.transport.http.QSListHandler" /> <parameter name="qs.method" value="org.apache.axis.transport.http.QSMethodHandler" /> <parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" /> <parameter name="qs.wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" /> </transport> <transport name="local"> <responseFlow> <handler type="LocalResponder" /> </responseFlow> </transport> <!-- 配置自己的服務 --> <service name="HelloService" provider="java:RPC"> <parameter name="allowedMethods" value="*" /> <parameter name="className" value="server.service.HelloServiceImpl" /> </service> </deployment>
(3)客戶端代碼
Test.java

1 package client; 2 3 import java.net.URL; 4 5 import javax.xml.rpc.ParameterMode; 6 7 import org.apache.axis.client.Call; 8 import org.apache.axis.encoding.XMLType; 9 10 public class Test { 11 12 public static void main(String args[]) throws Exception { 13 webservice_user(); 14 } 15 16 public static void webservice_user() throws Exception { 17 18 // 1.創建service對象,通過axis自帶的類創建 19 org.apache.axis.client.Service service = new org.apache.axis.client.Service(); 20 21 // 2.創建url對象 22 String wsdlUrl = "http://localhost:8080/WebService06_Security/services/HelloService?wsdl";// 請求服務的URL 23 URL url = new URL(wsdlUrl);// 通過URL類的構造方法傳入wsdlUrl地址創建URL對象 24 25 // 2.創建服務方法的調用者對象call,設置call對象的屬性 26 Call call = (Call) service.createCall(); 27 call.setTargetEndpointAddress(url);// 給call對象設置請求的URL屬性 28 String serviceName = "hello";// webservice的方法名 29 call.setOperationName(serviceName);// 給call對象設置調用方法名屬性 30 call.addParameter("s", XMLType.XSD_STRING, ParameterMode.IN);// 給call對象設置方法的參數名、參數類型、參數模式 31 call.setReturnType(XMLType.SOAP_STRING);// 設置調用方法的返回值類型 32 // call.setTimeout(new Integer(200));//設置超時限制 33 34 // 4.通過invoke方法調用webservice 35 String str = new String("pantp"); 36 String dept = (String) call.invoke(new Object[] { str });// 調用服務方法 37 38 // 5.打印返回結果 39 System.out.println("我是客戶端......."); 40 System.out.println(dept); 41 } 42 43 }
3.2測試開發的webservice
啟動tomcat,發布工程。
在瀏覽器中輸入wsdl地址,運行結果圖如下:
運行Test.java類:
(1)客戶端日志
(2)服務端日志
3.3加上users.lst的驗證
(1)增加users.lst文件
在工程的WEB-INF目錄下新建文件users.lst,文件內容如下:
(2)在 server-config.wsdd文件中增加驗證的配置
修改后完整的文件如下:

1 <?xml version="1.0" encoding="UTF-8"?> 2 <deployment xmlns="http://xml.apache.org/axis/wsdd/" 3 xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> 4 <globalConfiguration> 5 <parameter name="sendMultiRefs" value="true" /> 6 <parameter name="disablePrettyXML" value="true" /> 7 <parameter name="adminPassword" value="admin" /> 8 <parameter name="attachments.Directory" 9 value="D:\tomcat5\webapps\WebService\WEB-INF\attachments" /> 10 <parameter name="dotNetSoapEncFix" value="true" /> 11 <parameter name="enableNamespacePrefixOptimization" 12 value="false" /> 13 <parameter name="sendXMLDeclaration" value="true" /> 14 <parameter name="sendXsiTypes" value="true" /> 15 <parameter name="attachments.implementation" 16 value="org.apache.axis.attachments.AttachmentsImpl" /> 17 <requestFlow> 18 <handler type="java:org.apache.axis.handlers.JWSHandler"> 19 <parameter name="scope" value="session" /> 20 </handler> 21 <handler type="java:org.apache.axis.handlers.JWSHandler"> 22 <parameter name="scope" value="request" /> 23 <parameter name="extension" value=".jwr" /> 24 </handler> 25 </requestFlow> 26 </globalConfiguration> 27 <handler name="LocalResponder" 28 type="java:org.apache.axis.transport.local.LocalResponder" /> 29 <handler name="URLMapper" 30 type="java:org.apache.axis.handlers.http.URLMapper" /> 31 <handler name="Authenticate" 32 type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" /> 33 <service name="AdminService" provider="java:MSG"> 34 <parameter name="allowedMethods" value="AdminService" /> 35 <parameter name="enableRemoteAdmin" value="false" /> 36 <parameter name="className" value="org.apache.axis.utils.Admin" /> 37 <namespace>http://xml.apache.org/axis/wsdd/</namespace> 38 </service> 39 <service name="Version" provider="java:RPC"> 40 <parameter name="allowedMethods" value="getVersion" /> 41 <parameter name="className" value="org.apache.axis.Version" /> 42 </service> 43 44 <transport name="http"> 45 <requestFlow> 46 <handler type="URLMapper" /> 47 <handler 48 type="java:org.apache.axis.handlers.http.HTTPAuthHandler" /> 49 </requestFlow> 50 <parameter name="qs:list" 51 value="org.apache.axis.transport.http.QSListHandler" /> 52 <parameter name="qs:wsdl" 53 value="org.apache.axis.transport.http.QSWSDLHandler" /> 54 <parameter name="qs.list" 55 value="org.apache.axis.transport.http.QSListHandler" /> 56 <parameter name="qs.method" 57 value="org.apache.axis.transport.http.QSMethodHandler" /> 58 <parameter name="qs:method" 59 value="org.apache.axis.transport.http.QSMethodHandler" /> 60 <parameter name="qs.wsdl" 61 value="org.apache.axis.transport.http.QSWSDLHandler" /> 62 </transport> 63 <transport name="local"> 64 <responseFlow> 65 <handler type="LocalResponder" /> 66 </responseFlow> 67 </transport> 68 69 <!-- 配置自己的服務 --> 70 <service name="HelloService" provider="java:RPC"> 71 <parameter name="allowedMethods" value="*" /> 72 <parameter name="className" 73 value="server.service.HelloServiceImpl" /> 74 75 <!-- ===================采用webservice的users.lst的安全機制增加的配置部分 --> 76 <!-- 采用axis默認的handler來進行訪問權限的控制 --> 77 <requestFlow> 78 <handler name="SimpleAuthenticationHandler" 79 type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" /> 80 </requestFlow> 81 <!-- ===================采用webservice的users.lst的安全機制增加的配置部分 --> 82 83 </service> 84 85 </deployment>
(3)在客戶端請求代碼中加入用戶名和密碼
添加用戶名和密碼后完整的文件如下:

1 package client; 2 3 import java.net.URL; 4 5 import javax.xml.rpc.ParameterMode; 6 7 import org.apache.axis.client.Call; 8 import org.apache.axis.encoding.XMLType; 9 10 public class Test { 11 12 public static void main(String args[]) throws Exception { 13 webservice_user(); 14 } 15 16 public static void webservice_user() throws Exception { 17 18 // 1.創建service對象,通過axis自帶的類創建 19 org.apache.axis.client.Service service = new org.apache.axis.client.Service(); 20 21 // 2.創建url對象 22 String wsdlUrl = "http://localhost:8080/WebService06_Security/services/HelloService?wsdl";// 請求服務的URL 23 URL url = new URL(wsdlUrl);// 通過URL類的構造方法傳入wsdlUrl地址創建URL對象 24 25 // 2.創建服務方法的調用者對象call,設置call對象的屬性 26 Call call = (Call) service.createCall(); 27 call.setTargetEndpointAddress(url);// 給call對象設置請求的URL屬性 28 String serviceName = "hello";// webservice的方法名 29 call.setOperationName(serviceName);// 給call對象設置調用方法名屬性 30 call.addParameter("s", XMLType.XSD_STRING, ParameterMode.IN);// 給call對象設置方法的參數名、參數類型、參數模式 31 call.setReturnType(XMLType.SOAP_STRING);// 設置調用方法的返回值類型 32 // call.setTimeout(new Integer(200));//設置超時限制 33 34 //-----------------------------采用webservice的users.lst的安全機制增加的------------------------------------- 35 //此處的用戶名和密碼對應WEB-INF目錄下users.lst文件中的用戶名和密碼 36 call.getMessageContext().setUsername("pantp"); 37 call.getMessageContext().setPassword("123456"); 38 //-----------------------------采用webservice的users.lst的安全機制增加的------------------------------------- 39 40 // 4.通過invoke方法調用webservice 41 String str = new String("pantp"); 42 String dept = (String) call.invoke(new Object[] { str });// 調用服務方法 43 44 // 5.打印返回結果 45 System.out.println("我是客戶端......."); 46 System.out.println(dept); 47 } 48 49 }
3.4測試webservice通過users.lst實現的安全機制
(1)輸入正確的用戶名和密碼
客戶端日志:
服務端日志:
(2)輸入錯誤的用戶名或密碼
客戶端日志:
服務端日志:
后台沒有任何日志輸出;
總結:
開發通過webservice自帶的驗證機制實現步驟如下:
1.先不考慮安全機制的問題,開發一個需要的webservice服務和客戶端,並測試通過;
2.在WEB-INF目錄下新建一個文件users.lst,文件名必須一模一樣,然后在文件中加入允許的用戶名和密碼;
3.在wsdd配置文件中對應的服務中加入SimpleAuthenticationHandler的配置;
4.在客戶端訪問時增加用戶名和密碼的設置;