2011-07-09 11 views
6

Tworzę klienta dla usługi mydlanej .net, ale mam problem z ustaleniem, jak poprawnie przekazać hasło. Oto moja „ustalony” przykład hasło:Klient CXF Security

@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"); 
} 

}

Co naprawdę chcę zrobić, to przekazać hasło do obsługi połączenia zwrotnego. Przykłady, które widziałem w dokumentacji CXF wdrożenia zwrotnego albo „na sztywno” (jak ja w tym przykładzie) lub jako funkcja nazwa użytkownika:

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

Żadna z tych moich potrzeb. Czy istnieje sposób, że mogę zrobić coś jak następuje:

@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: Próbowałem tak rozplanowany tutaj [http://stackoverflow.com/questions/5906154/apache-cxf-credentials-not-being-sent-from-wss4joutinterceptor], ale bez powodzenia – jayraynet

Odpowiedz

9

Zastosowanie PW_CALLBACK_REF zamiast PW_CALLBACK_CLASS i zdać instancja obiektu, zamiast klasy statycznej. Możesz wprowadzić hasło do wspomnianego obiektu.

Coś jak:

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

Byłem również w stanie wykonać następujące czynności:

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

Jak uzyskać dostęp do parametru "hasło" z wewnątrz Handler? Lub nie musisz definiować niestandardowego programu obsługi w tym przypadku? –

0

zawsze stosować następujący sposób dodawania właściwości do żądania kontekst uwierzytelniania poziomu HTTP i CallbackHandler dodawania znacznik nazwy poziomu wiadomości.

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"); 

     } 

     } 


    } 

}