2011-07-09 311 views
6

我正在創建一個.net soap web服務的客戶端,但在解決如何正確傳遞密碼時遇到困難。這是我的「硬編碼」密碼例如:CXF客戶端安全

@Test 
public void exploratorySecurityTest() { 
    String username = "user"; 
    String password = "pwd"; 

    UserStoryService service = new UserStoryService(); 
    UserStoryServiceSoap port = service.getUserStoryServiceSoap(); 

    //initialize security 
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 
    Map<String, Object> outProps = new HashMap<String, Object>(); 
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
    outProps.put(WSHandlerConstants.USER, username); 
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName()); 
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 
    cxfEndpoint.getOutInterceptors().add(wssOut); 

    int storyId = 33401; 
    UserStoryDTO userStoryDTO = port.getByID(storyId); 

    //success if no error 
} 

public class ClientPasswordCallback implements CallbackHandler { 

@Override 
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; 
    pc.setPassword("pwd"); 
} 

}

我真正想要做的是密碼傳遞到回調處理程序。我的CXF文檔中所看到的例子實現回調無論是「硬編碼」或用戶名的功能(如我在這個例子中所做的那樣):

if (pc.getIdentifier().equals("user")) { 
    pc.setPassword("pwd"); 
} 

這些都不滿足我的需求。有沒有一種方法,我可以做類似如下:

@Test 
public void exploratorySecurityTest() { 
    String username = "user"; 
    String password = "pwd"; 

    UserStoryService service = new UserStoryService(); 
    UserStoryServiceSoap port = service.getUserStoryServiceSoap(); 

    //initialize security 
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 
    Map<String, Object> outProps = new HashMap<String, Object>(); 
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
    outProps.put(WSHandlerConstants.USER, username); 

      //pass the password here? 
      outProps.put("password", password); 

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName()); 
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 

    cxfEndpoint.getOutInterceptors().add(wssOut); 
      ... 
} 
+0

BTW:我已經嘗試了這裏的佈局方式[http://stackoverflow.com/questions/5906154/apache-cxf-credentials-not-being-sent-from-wss4joutinterceptor],但沒有運氣 – jayraynet

回答

9

使用PW_CALLBACK_REF代替PW_CALLBACK_CLASS,並通過實例化對象,而不是靜態類。您可以在所述對象中注入密碼。

喜歡的東西:

outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 
    CXFClientPasswordHandler handler = new CXFClientPasswordHandler(); 
    handler.setPassword(password); 
    outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler); 
3

我也能做到以下幾點:添加屬性,請求HTTP級別認證的CallbackHandler上下文加入

org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 

    Map<String, Object> outProps = new HashMap<String, Object>(); 

    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 

    System.out.println("initialize security for user " + this.username); 
    outProps.put(WSHandlerConstants.USER, this.username); 
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 

    Map<String, Object> ctx = ((BindingProvider) obj).getRequestContext(); 
    ctx.put("password", this.password); 

    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 
    cxfEndpoint.getOutInterceptors().add(wssOut); 
+0

如何從Handler內部訪問「密碼」參數?或者你不需要在這種情況下定義一個自定義處理程序? –

0

我一直用下面的方式消息級別用戶名令牌。

org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj); 
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 


System.out.println("initialize security for user " + this.username); 
outProps.put(WSHandlerConstants.USER, this.username); 
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 

Map<String, Object> requestContext = ((BindingProvider) obj).getRequestContext(); 


//For message level authentication 
requestContext.put("ws-security.username", "Ron"); 
requestContext.put("ws-security.callback-handler", "com.ws.cxf.client.callback.UTPasswordCallback"); 

//For endpoint level authentication, HTTP Basic/Digest 
requestContext.put(BindingProvider.USERNAME_PROPERTY, username); 
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password); 




class UTPasswordCallback implements CallbackHandler { 

@Override 
public void handle(Callback[] callbacks) throws IOException, 
     UnsupportedCallbackException { 


    for(Callback cb:callbacks){ 
     WSPasswordCallback pcallback = (WSPasswordCallback)cb; 
     if(pcallback.getUsage()==WSPasswordCallback.USERNAME_TOKEN) 
     { 

      if(pcallback.getIdentifier().equals("Ron")) 
       pcallback.setPassword("noR"); 

     } 

     } 


    } 

}