簡體   English   中英

與Web服務的相互身份驗證

[英]Mutual-authentication with web services

目前,只要客戶端使用Web瀏覽器訪問網站,我就成功實現了相互身份驗證安全性,因為瀏覽器會為您處理所有證書交換。 現在,我需要創建一個安全的界面,用戶可以使用服務器所需的相互身份驗證通過HTTPS訪問Web服務。

首先,有沒有人知道的資源可以幫助我嗎? 我已經找了很長時間沒找到。 任何其他人可以給我如何解決這個問題的提示?

其次,我認為我最大的障礙是我對如何處理證書缺乏了解。 如何協商接受服務器密鑰並將自己的密鑰提供給服務器? 這是Java。

我花了很長時間在這上面,但我終於找到了一個實際可行的例子。 它是基於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-listener上啟用Security,勾選SSL3,TLS和Client Authentication框,將Certificate NickName設置為server,將密鑰存儲設置為config \\ keystore.jks,將Trust Store設置為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 Service,然后選擇“編輯Web服務屬性”。 選中Secure Service框並選擇Mutual Certificates Security作為安全機制。 單擊Configure ...按鈕並勾選Encrypt Signature框。 現在取消勾選Use Development 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());
}

將webservices-api.jar復制到Java \\ jdk1.6 \\ jre \\ lib \\ endorsed目錄中。 右鍵單擊Web Service引用,然后選擇“編輯Web服務屬性”。 將密鑰庫位置設置為client1.jks並將別名設置為client1 將truststore位置設置為client1.jks並將別名設置為server

希望您現在可以運行您的客戶端,您應該看到如下輸出: EMAILADDRESS=bob@anonymous.org, CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

對於在瀏覽器之外使用SSL(也稱為雙向SSL)進行相互身份驗證,您需要......實際上,讓我們先看看您對單向SSL的需求:

  1. 服務器密鑰庫
  2. 客戶端信任庫

服務器密鑰庫包含服務器(可能是自簽名)證書和私鑰。 服務器使用此存儲來簽署消息並將憑據返回給客戶端。

客戶端信任庫包含服務器的(自簽名)證書(從服務器密鑰庫提取到獨立證書中,不包含服務器私鑰)。 如果證書未由您在JRE捆綁的信任庫中已擁有證書的可信CA簽名,則必須執行此操作。 此步驟允許創建信任鏈。

有了這個,您可以實現單向SSL(傳統的用例)。

要實現雙向SSL,您需要將此設置設置為“對稱”,因此我們需要添加:

  1. 客戶端密鑰庫
  2. 服務器信任庫

客戶端密鑰庫包含客戶端(可能是自簽名)證書和私鑰。 客戶端使用此存儲的目的與服務器密鑰庫相同,即在TLS相互身份驗證握手期間將客戶端憑據發送到服務器。

服務器信任庫包含客戶端(自簽名)獨立證書(從客戶端密鑰庫提取到獨立證書,而不包含客戶端私鑰)。 出於與前面提到的完全相同的原因,這是必需的。

一些資源可以幫助您生成所有這些東西並實現最終解決方案:

如果Web服務庫使用標准java.net.URL類作為HTTP客戶端,則可以設置一些系統屬性,並且內置HTTPS支持將處理雙向身份驗證。

必要的屬性是:

  • javax.net.ssl.trustStore :包含根CA證書
  • javax.net.ssl.keyStore :包含客戶端證書和私鑰
  • javax.net.ssl.keyStorePassword :保護客戶端私鑰的密碼

這些設置成為進程的所有SSL連接的默認設置。 如果你想要更好的控制,你必須設置自己的SSLContext 您的Web服務運行時是否可行取決於您選擇的運行時。

本博客文章中給出了一個簡單的配方。

但我認為真正的答案可能取決於您使用什么Java API來實現客戶端HTTP交互。 例如,看起來你會使用JAX-RPC做一些不同的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM