首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web 服務:Axis2 WS-Security 簽名與加密完整實戰

     編輯:Java 相關知識

前言:為什麼需要 WS-Security?

SOAP 訊息在網路上傳輸面臨三大風險:

  • 機密性:訊息內容被竊聽。
  • 完整性:訊息被竄改。
  • 真實性:無法驗證發送者身分。

WS-Security 標準在 SOAP Header 層面提供**簽名**、**加密**、**時間戳**、**安全權杖**等機制,結合公開金鑰加密體系,端到端保護訊息安全,不依賴傳輸層(如 HTTPS)。

核心密碼學基礎回顧

非對稱加密(公開金鑰加密)

  • 金鑰對:公開金鑰(可公開分發)+ 私有金鑰(嚴格保密)。
  • 公開金鑰加密 → 僅私有金鑰能解密 → **機密性**(任何人可加密給持有者)。
  • 私有金鑰加密(簽名) → 公開金鑰可解密驗證 → **真實性/完整性**(只有持有者能產生簽名)。

數位簽名流程

  1. 發送方對訊息計算雜湊值。
  2. 用私有金鑰加密雜湊值 → **數位名**。
  3. 接收方用發送方公開金鑰解密簽名得雜湊值,並自行計算訊息雜湊值,比對一致則驗證通過。

XML 標準化

XML 空白、屬性順序不影響語義,簽名前必須將 XML 轉為標準形式,使用 Exclusive XML Canonicalization (Exc-C14N) 算法。

憑證與金鑰庫

  • X.509 憑證:公開金鑰 + 身分資訊 + CA 簽名。
  • Keystore (JKS/PKCS12):加密儲存私有金鑰與憑證鏈,需密碼保護。
  • Java 內建 keytool 管理金鑰庫。

Axis2 + Rampart 實作環境建置

  1. 安裝 Axis2,確認 repository/modules/rampart-*.mar 存在。
  2. 加入 Bouncy Castle Provider:
    修改 $JAVA_HOME/jre/lib/security/java.security,加入 security.provider.x=org.bouncycastle.jce.provider.BouncyCastleProvider。
    將 bcprov-jdk*.jar 放入 Axis2 lib/ 與 Webapp WEB-INF/lib/。
  3. 專案結構:build.xml、library.wsdl、Policy 檔、密碼回調類。

案例一:純簽名

客戶端 Policy (sign-policy-client.xml)

<wsp:Policy wsu:Id="SignOnly">
  <wsp:ExactlyOne><wsp:All>
    <sp:AsymmetricBinding>
      <wsp:Policy>
        <sp:InitiatorToken>  <sp:X509Token sp:IncludeToken=".../AlwaysToRecipient"/> </sp:InitiatorToken>
        <sp:RecipientToken> <sp:X509Token sp:IncludeToken=".../AlwaysToInitiator"/> </sp:RecipientToken>
        <sp:AlgorithmSuite> <sp:TripleDesRsa15/> </sp:AlgorithmSuite>
        <sp:Layout> <sp:Strict/> </sp:Layout>
        <sp:IncludeTimestamp/>
        <sp:OnlySignEntireHeadersAndBody/>
      </wsp:Policy>
    </sp:AsymmetricBinding>
    <sp:SignedParts> <sp:Body/> </sp:SignedParts>

    <ramp:RampartConfig>
      <ramp:user>clientkey</ramp:user>
      <ramp:passwordCallbackClass>com.sosnoski.ws.library.adb.PWCBHandler</ramp:passwordCallbackClass>
      <ramp:signatureCrypto>
        <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
          <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
          <ramp:property name="org.apache.ws.security.crypto.merlin.file">client.keystore</ramp:property>
          <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.password">nosecret</ramp:property>
        </ramp:crypto>
      </ramp:signatureCrypto>
    </ramp:RampartConfig>
  </wsp:All></wsp:ExactlyOne>
</wsp:Policy>

關鍵配置解析

  • InitiatorToken:客戶端簽名用的私鑰,憑證隨訊息發送。
  • RecipientToken:服務端回覆簽名用的私鑰,憑證隨回覆發送。
  • AlgorithmSuite:TripleDesRsa15 代表對稱加密 3DES,非對稱 RSA-v1.5,雜湊 SHA-1。
  • SignedParts:僅簽名 SOAP Body。
  • RampartConfig:指定 keystore 別名、密碼回調類、簽名加密提供者。

密碼回調類

public class PWCBHandler implements CallbackHandler {
    public void handle(Callback[] callbacks) {
        for (Callback cb : callbacks) {
            WSPasswordCallback pwcb = (WSPasswordCallback) cb;
            if (pwcb.getUsage() == WSPasswordCallback.SIGNATURE ||
                pwcb.getUsage() == WSPasswordCallback.DECRYPT) {
                if ("clientkey".equals(pwcb.getIdentifier())) {
                    pwcb.setPassword("clientpass"); // 私鑰密碼
                }
            }
        }
    }
}

案例二:簽名 + 加密

Policy 差異 (signencr-policy-client.xml)

<sp:RecipientToken>
  <sp:X509Token sp:IncludeToken=".../Never">
    <wsp:Policy> <sp:RequireThumbprintReference/> </wsp:Policy>
  </sp:X509Token>
</sp:RecipientToken>
<sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts>

<ramp:encryptionUser>serverkey</ramp:encryptionUser>
<ramp:encryptionCrypto> ... 同 signatureCrypto 設定 ... </ramp:encryptionCrypto>

關鍵變化

  • RecipientToken IncludeToken="Never":不傳送服務端憑證,改用 **Thumbprint (SHA-1 雜湊)** 參考,減小訊息體積。
  • 新增 EncryptedParts:指定加密 SOAP Body。
  • encryptionUser:指定用於加密的公開金鑰別名(服務端憑證)。
  • encryptionCrypto:指定存放服務端憑證的 keystore。

加密流程(混合加密)

  1. 產生隨機**對稱金鑰**(Session Key)。
  2. 用對稱金鑰加密 SOAP Body → <xenc:EncryptedData>。
  3. 用服務端**公開金鑰**加密對稱金鑰 → <xenc:EncryptedKey> 放在 Security Header。
  4. 服務端用私鑰解開對稱金鑰,再解密 Body。
混合加密結合非對稱(金鑰交換)與對稱(大量資料)優點,效能與安全並重。

自簽憑證產生與交換

# 產生服務端金鑰對與憑證
keytool -genkey -alias serverkey -keypass serverpass -keyalg RSA -sigalg SHA1withRSA -keystore server.keystore -storepass nosecret

# 產生客戶端金鑰對與憑證
keytool -genkey -alias clientkey -keypass clientpass -keyalg RSA -sigalg SHA1withRSA -keystore client.keystore -storepass nosecret

# 導出服務端憑證並導入客戶端信任庫
keytool -export -alias serverkey -keystore server.keystore -storepass nosecret -file servercert.cer
keytool -import -alias serverkey -keystore client.keystore -storepass nosecret -file servercert.cer

# 導出客戶端憑證並導入服務端信任庫
keytool -export -alias clientkey -keystore client.keystore -storepass nosecret -file clientcert.cer
keytool -import -alias clientkey -keystore server.keystore -storepass nosecret -file clientcert.cer

將產生的 client.keystore 放入客戶端 classpath,server.keystore 放入服務端 classpath。

實際 SOAP 訊息解析

純簽名訊息

Header 包含:Timestamp、BinarySecurityToken(客戶端憑證)、Signature(SignedInfo + SignatureValue + KeyInfo)。Body 為明文。

簽名+加密訊息

Header 額外包含:EncryptedKey(加密的對稱金鑰 + Thumbprint 參考服務端憑證)。Body 替換為 EncryptedData。

效能與部署建議

  1. 簽名開銷中等;加密開銷較大(特別是非對稱運算)。高流量系統建議啟用硬體加速(HSM)或離載給 API Gateway。
  2. Keystore 密碼在程式碼中以明文或配置檔出現,**務必保護伺服器實體安全與備份加密**。
  3. 生產環境**必須使用受信 CA 簽發的憑證**,自簽憑證僅限測試/內網。
  4. 定期輪換金鑰對與憑證,建立撤銷機制(CRL/OCSP)。
  5. WS-SecurityPolicy 允許針對不同 Operation 套用不同 Policy,精細控制安全等級。

總結

Axis2 + Rampart 提供標準相容的 WS-Security 實作。透過 Policy 驅動配置,分離業務邏輯與安全邏輯。掌握「非對稱加密基礎 → Policy 配置 → Keystore 管理 → 訊息結構」四大支柱,即可建構企業級安全 Web 服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved