目前,只要客戶端使用Web瀏覽器訪問網站,我就已經成功地實現了相互驗證安全性,因爲瀏覽器會爲您處理所有證書交換。現在我需要創建一個安全接口,用戶可以使用該接口通過HTTPS訪問Web服務,並使用服務器所需的相互身份驗證。與Web服務相互驗證
首先,有沒有任何資源可以幫助我呢?我尋找了相當一段時間,什麼都沒發現。任何人都可以給我如何去做這個提示?其次,我認爲我最大的障礙是我缺乏對如何處理證書的理解。我該如何協商接受服務器密鑰並將自己的密鑰呈現給服務器?這是用Java編寫的。
目前,只要客戶端使用Web瀏覽器訪問網站,我就已經成功地實現了相互驗證安全性,因爲瀏覽器會爲您處理所有證書交換。現在我需要創建一個安全接口,用戶可以使用該接口通過HTTPS訪問Web服務,並使用服務器所需的相互身份驗證。與Web服務相互驗證
首先,有沒有任何資源可以幫助我呢?我尋找了相當一段時間,什麼都沒發現。任何人都可以給我如何去做這個提示?其次,我認爲我最大的障礙是我缺乏對如何處理證書的理解。我該如何協商接受服務器密鑰並將自己的密鑰呈現給服務器?這是用Java編寫的。
一個簡單的配方在this blog entry中給出。
但我認爲真正的答案可能取決於您使用什麼Java API來實現您的客戶端HTTP交互。例如,它看起來像你會使用JAX-RPC做a bit differently。
如果Web服務庫使用標準java.net.URL
類作爲HTTP客戶端,則可以設置一些system properties,雙向認證將由內置HTTPS支持處理。
javax.net.ssl.trustStore
:包含根CA證書javax.net.ssl.keyStore
:包含客戶證書和私鑰javax.net.ssl.keyStorePassword
:密碼保護客戶端的私鑰這些設置成爲進程所有SSL連接的默認設置。如果你想更好的控制,你必須建立你自己的SSLContext
。您的webservice運行時是否可能取決於您選擇的運行時間。
對於SSL(又名雙向SSL)在瀏覽器之外的相互認證,你需要......嗯,其實,讓我們看看你需要什麼單向SSL第一:
服務器密鑰庫包含服務器(可能是自簽名)證書和私鑰。該存儲由服務器用於簽署消息並向客戶端返回憑證。
客戶端信任庫包含服務器的(自簽名)證書(從服務器密鑰庫提取到獨立證書中,沒有服務器私鑰)。如果證書未由信任的CA簽名,那麼您已在與JRE捆綁在一起的truststore中擁有證書。這一步可以創建一個信任鏈。
有了這個,您可以實現單向SSL(傳統用例)。
要實現雙向SSL,你需要這個設置的「對稱」,所以我們需要添加:
的客戶端密鑰庫包含客戶端(可能是自簽名的)證書和私鑰。該存儲由客戶用於與服務器密鑰庫相同的目的,即在TLS相互認證握手期間將客戶證書發送到服務器。
服務器信任庫包含客戶端(自簽名)獨立證書(從客戶端密鑰庫中提取到獨立證書中,不包含客戶端私鑰)。這與前面提到的完全相同的原因是必需的。
一些資源,幫助您生成所有這些東西,並實現最終的解決方案:
我花了很長在這個時候,但我終於找到了一個實例盟友的作品。它基於Glassfish和Netbeans,但我想你可以在其他環境(如Eclipse和Tomcat)中使用它,如果你玩過它的話。
http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511
我雖然發現的問題是,當你想用自己的證書,而不是隨之而來的GlassFish預裝的人。
注意:我不是安全專家。不要將其部署到生產環境!
要做到這一點,我使用NetBeans 6.9,JDK 1.6,GlassFish的3.0.1和OpenSSL V1.0(我使用的是非官方Win32的二進制文件)
# Create the CA
mkdir ca server client
cd ca
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem
echo 02 > serial.txt
cd ..
# Creating the Server Keystore
openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer
# Create the Client Keystore
openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req
openssl x509 -extensions usr_cert -extfile C:\testbed\OpenSSL-Win32\bin\openssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer
# Import public keys and certificates into each others keystores
keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks"
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts"
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup"
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks"
在GlassFish管理控制檯,啓用HTTP監聽器的安全性,勾選SSL3,TLS和客戶端身份驗證框,將證書NickName設置爲服務器,將密鑰庫設置爲config \ keystore.jks,將信任庫設置爲config \ keystore.jks,將信任算法設置爲PKIX並將最大證書長度保留爲5.
在NetBeans中,創建一個新的Web應用程序項目。其中,創建一個新的Web服務。
我的web服務代碼是這樣的:
@WebService()
public class ListProducts {
@Resource WebServiceContext context;
@WebMethod(operationName = "listProducts")
public String listProducts() {
return context.getUserPrincipal().toString();
}
}
右鍵單擊Web服務,然後選擇編輯Web服務屬性。勾選安全服務框並選擇相互證書安全性作爲安全機制。點擊Configure ...按鈕,並勾選Encrypt Signature框。現在取消Use Use Defaults框,然後點擊Keystore按鈕。設置server.jks密鑰庫的位置並選擇server
別名。對Truststore配置執行相同操作(儘管您不必在此選擇別名)。
將client1.p12客戶端證書導入瀏覽器。將Web服務部署到Glassfish。在瀏覽器中打開Web服務,並通過HTTPS瀏覽已部署的WSDL。下載WSDL和任何其他模式。將任何引用的模式重命名爲本地副本,以便在使用WSDL2Java時,NetBeans不會使用任何遠程資源。 (這一段是因爲您已將WSDL限制爲具有批准證書的客戶端,但NetBeans無法遠程獲取它,因爲它無法訪問有問題的證書)。
創建一個新的Java項目。創建一個新的Web服務客戶端。出現提示時,將NetBeans指向保存的WSDL文件。導入METRO2.0庫文件(C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar
)。我的代碼是這樣的:
public static void main(String[] args) {
System.getProperties().put("javax.net.ssl.keyStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit");
System.getProperties().put("javax.net.ssl.trustStore", "C:\\NetBeansProjects\\security-04\\ssl\\client\\client1.jks");
System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit");
System.out.println(new ListProductsService().getListProductsPort().listProducts());
}
複製web服務-api.jar文件到您的Java \ JDK1.6 \ JRE \ LIB \ endorsed目錄。 右鍵單擊Web服務引用並選擇編輯Web服務屬性。將密鑰庫位置設置爲client1.jks,並將別名設置爲client1
。將信任庫位置設置爲client1.jks,並將別名設置爲server
。
希望你現在可以運行你的客戶,你應該看到像這樣的輸出: [email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US
雖然你已經解釋了相互認證的概念相當不錯,鏈接是不是非常有幫助的。自2006年以來,Java Web服務安全性發生了一些變化! :) – Catchwa 2010-06-29 04:54:50