2012-11-18 26 views
5

Podążyłem za miauknięciem kilku tutoriali i ani trochę z powodzeniem!Apache CXF i WS-Security - Hasło oddzwonienia

Próbuję uzyskać Apache CXF i WS-Security, aby oddzwonić do mojego uwierzytelniającego Spring Security. Wszystko jest bliskie pracy, ale w chwili obecnej mam problem z uzyskaniem hasła, aby zapewnić ochronę Spring przed powrotem do WS-back.

Handler poniżej zostanie uszkodzony, ale pc.getPassword() ma wartość null. Chcę to być hasło wysłane Mydło więc mogę przekazać je do wiosny

public class ServerPasswordCallback implements CallbackHandler { 

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

    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; 

    pc.setPassword(pc.getPassword()); 
} 

Moja Interceptor jest skonfigurowany jako tak

<bean id="wsAuthenticationInterceptor" class="com.olympus.viewtheworld.server.security.auth.WSAuthenticationInInterceptor"> 
    <constructor-arg index="0"> 
     <map key-type="java.lang.String" value-type="java.lang.Object"> 
      <entry key="action" value="UsernameToken" /> 
      <entry key="passwordType" value="PasswordText" /> 
      <entry key="passwordCallbackClass" value="com.olympus.viewtheworld.server.security.auth.ServerPasswordCallback" /> 
     </map> 
    </constructor-arg> 
    <property name="authenticationManager" ref="authenticationManager"/> 
</bean> 

<jaxws:endpoint id="secureHelloService" 
       implementor="#secureHelloServiceImpl" 
       implementorClass="com.olympus.viewtheworld.server.service.Impl.SecureHelloServiceImpl" 
       address="/SoapService/secure/hello"> 
    <jaxws:serviceFactory> 
     <ref bean="jaxws-and-aegis-service-factory" /> 
    </jaxws:serviceFactory> 
    <jaxws:inInterceptors> 
     <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/> 
     <ref bean="wsAuthenticationInterceptor" /> 
    </jaxws:inInterceptors> 
</jaxws:endpoint> 

i żądanie mydło przesyłam z SoapUI jest

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://test/"> 
    <soapenv:Header> 
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
<wsse:UsernameToken> 
<wsse:Username>rob2</wsse:Username> 
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">passwordxx</wsse:Password> 
</wsse:UsernameToken> 
</wsse:Security> 
</soapenv:Header> 
    <soapenv:Body> 
     <test:hello> 
     <!--Optional:--> 
     <hello>asdf</hello> 
     </test:hello> 
    </soapenv:Body> 
</soapenv:Envelope> 

Wersja mądry jest wiosna 3.1 i CXF 2.7.0

Co muszę zrobić, aby zobaczyć „passwordxx "w klasie ServerPasswordCallback? Czy to prośba o mydło, konfiguracja czy po prostu zła ?!

Cheers, Rob

Odpowiedz

0

Ok, więc to nie jest idealne rozwiązanie i mam nadzieję, że lepsza odpowiedź przyjdzie trochę później wzdłuż linii, najprawdopodobniej, kiedy mam trochę więcej czasu, aby spojrzeć na to.

Używam wyrażenia regularnego do sprawdzenia pełnego pakietu i wyciągnięcia pola hasła. Kod znajduje się poniżej. Zostanie zaktualizowany później, kiedy wypracuję właściwą drogę, aby to zrobić, ponieważ jest to defintley, nie to!

WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; 
     String mydata= pc.getRequestData().getMsgContext().toString();   
     Pattern pattern = Pattern.compile("<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">(.*?)<"); 
     Matcher matcher = pattern.matcher(mydata); 
     if (matcher.find()) 
     { 
      pc.setPassword(matcher.group(1)); 
     } 
1

Jak wynika z dokumentacji na org.apache.ws.security.handler.WSHandlerConstants.PW_CALLBACK_CLASS że metoda powinna zamiast zadzwonić pc.setPassword z przechowywanym hasłem porównania hasło warunkiem użytkownika przed jako argument, zamiast hasła, pod warunkiem użytkownika samej:

ten oznacza odwołanie do klasy implementacji CallbackHandler używanej do uzyskania uzyskania haseł. Wartością tego znacznika musi być nazwa klasy instancji javax.security.auth.callback.CallbackHandler instancji . Funkcja zwrotna

javax.security.auth.callback.CallbackHandler.handle(javax.security.auth.callback.Callback[])

dostaje tablicę obiektów org.apache.ws.security.WSPasswordCallback. Używany jest tylko pierwszy wpis tablicy. Ten obiekt zawiera nazwę użytkownika/nazwę klucza jako identyfikator. Program obsługi wywołania zwrotnego musi ustawić hasło lub klucz związany z tym identyfikatorem przed jego zwróceniem.Aplikacja może ustawić ten parametr przy użyciu następującej metody:

call.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, "PWCallbackClass");


Używam org.apache.ws.security.validate.Validator aby sprawdzić ważność dostarczonego hasła i ustawienia kontekstu zabezpieczeń Wiosna tam:

@Bean(name = "wssforjInInterceptor") 
public WSS4JInInterceptor wssforjInInterceptor() { 
    // Configure how we ask for username and password 
    Map<String, Object> props = new HashMap<>(); 
    props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
    props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); 

    // Password callback 
    props.put(WSHandlerConstants.PW_CALLBACK_REF, passwordCallbackHandler()); 

    // Validator registration 
    Map<QName, Object> validators = new HashMap<>(); 
    String WSS_WSSECURITY_SECEXT_1_0_XSD = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 
    QName qName = new QName(WSS_WSSECURITY_SECEXT_1_0_XSD, WSHandlerConstants.USERNAME_TOKEN, ""); 
    validators.put(qName, usernameTokenValidator()); 
    props.put(WSS4JInInterceptor.VALIDATOR_MAP, validators); 

    WSS4JInInterceptor wss4jInInterceptor = new WSS4JInInterceptor(props); 
    return wss4jInInterceptor; 
} 

Nie jestem pewien, czy to podejście jest lepsze czy gorsze (byłbym wdzięczny za pewne opinie na ten temat), ale może jest to przydatne dla następna osoba, która natknie się na tę kwestię. Wydaje się, że brak jest przyzwoitej, aktualnej dokumentacji dotyczącej integracji zabezpieczeń Spring i CXF.