2013-04-15 77 views
6

我正在使用Apache CXF構建Web服務。它使用Apache WSS4J提供WS-Security功能。我需要做一個SOAP請求並且它必須被簽名。如何讓WSS4J從回調中加載密鑰庫密碼?

這是性質的內容文件我傳遞給WSS4J:

org.apache.ws.security.crypto.provider = org.apache.ws.security.components.crypto.Merlin 
org.apache.ws.security.crypto.merlin.keystore.type = PKCS12 
org.apache.ws.security.crypto.merlin.keystore.provider = BC 
org.apache.ws.security.crypto.merlin.keystore.password = 12345678 
org.apache.ws.security.crypto.merlin.keystore.alias = my-alias 
org.apache.ws.security.crypto.merlin.keystore.file = my_certificate.p12 

我想用自己的密碼寫爲純文本,以擺脫線。我刪除該行並提供一個密碼回調處理程序來我WSS4JOutInterceptor,如上面的代碼:

public SoapInterceptor newSignerInterceptor() { 
    Map<String, Object> outProps = new HashMap<String, Object>(); 
    outProps.put(WSHandlerConstants.ACTION, "Signature"); 
    outProps.put(WSHandlerConstants.USER, config.getKeyAlias()); 
    outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference"); 
    outProps.put(WSHandlerConstants.USE_REQ_SIG_CERT, WSHandlerConstants.SIGNATURE_USER); 
    outProps.put(WSHandlerConstants.USE_SINGLE_CERTIFICATE, "false"); 
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, this.getClass().getName()); 
    outProps.put(WSHandlerConstants.SIG_PROP_FILE, config.getPropertiesFileName()); 
    return new WSS4JOutInterceptor(outProps); 

} 

@Override 
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
    for (int i = 0; i < callbacks.length; i++) { 
     if (callbacks[i] instanceof WSPasswordCallback) { 
      ((WSPasswordCallback) callbacks[i]).setPassword(password); 
     } 
    } 
} 

但沒有奏效。它在屬性文件中找不到密碼並使用默認密碼「security」。

如何讓它使用回調獲取密碼?

回答

5

您可以實現CallbackHandler

public class PasswordCallbackHandler implements CallbackHandler { 

    @Override 
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
     for(Callback callBack:callbacks){ 
      if(callBack instanceof WSPasswordCallback){ 
       ((WSPasswordCallback)callBack).setPassword("password"); 
      } 
     } 
    } 
} 

然後將處理程序添加到屬性:

outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallbackHandler.class); 

你也可以使用PW_CALLBACK_REF要設置處理的參考。

-1

Merlin不會調用Keystore密碼的回調,因此密碼始終必須位於屬性文件中。幸運的是它可以被加密。

該解決方案很好地描述這裏: Encrypting passwords in Crypto property files

從上面的鏈接複製

解決方案:

  1. 下載jasypt-1.9.2-dist.zip
  2. 與此獲得一個編碼的密碼命令encrypt input=real_keystore_password password=master_password algorithm=PBEWithMD5AndTripleDES
  3. 複製的輸出(例如:0laAaRahTQJzlsDu771tYi)
  4. 當你正在使用這個algorith m,您需要Java密碼學擴展(JCE)無限強度 。放入您的JDK。
  5. 把編碼輸出中的屬性

    org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin 
    
    org.apache.wss4j.crypto.merlin.keystore.type=jks 
    org.apache.wss4j.crypto.merlin.keystore.password=ENC(0laAaRahTQJzlsDu771tYi) 
    
    org.apache.wss4j.crypto.merlin.keystore.alias=my_alias 
    org.apache.wss4j.crypto.merlin.keystore.file=/etc/cert/my_keystore.jks 
    
  6. 在的CallbackHandler,就把MASTER_PASSWORD至極你用來 生成的編碼之一:

    public class WsPasswordHandler implements CallbackHandler { 
    @Override 
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
    
        for (Callback callback: callbacks){ 
         WSPasswordCallback pwdCallback= (WSPasswordCallback) callback; 
         final int usage =pwdCallback.getUsage(); 
         if (usage == WSPasswordCallback.SIGNATURE || usage==WSPasswordCallback.DECRYPT) { 
         pwdCallback.setPassword("parKeyPassword"); 
        } 
        if (usage==WSPasswordCallback.PASSWORD_ENCRYPTOR_PASSWORD){ 
         pwdCallback.setPassword("master_password"); 
        } 
        }   
    } 
    

    }