Zabezpieczony Web Service

0

Witam.

Poraz kolejny mam pytanie związane z usługami sieciowymi JAX-WS.
Udało mi się znaleŹć przykład zabezpieczenia Web Service przy użyciu bibliotek XWSS/WSIT
https://xwss.dev.java.net/Securing_JAVASE6_WebServices.html

Postanowiłem zaadaptować ten przykład, do jax-ws ri. Niestety Tomcat wyrzuca mi wyjątek NoSuchMethodError:

com.sun.xml.ws.api.addressing.AddressingVersion.isEnabled(Lcom/sun/xml/ws/api/WSBinding;)Z

Potem zobaczyłem, że nie brakuje mi bibliotek WSIT, po ich dołączeniu Tomcat znów wyżuca wyjątek NoSuchMethodError:

com.sun.xml.ws.api.WSBinding.getFeature(Ljava/lang/Class;)L

Wówczas zrozumiałem, że biblioteki jaxws-ri i WIST "nachodzą na siebie", tj. mają te same nazwy klas i pakietów.

Moje pytanie, więc jest takie: Czy da się postawić Web Service RI zabezpieczając go XWSS?
Jeśnie nie, to jak uzyskać podobny efekt.

Na wszelki wypadek zamieszczam co zrobiłem:

  1. Biblioteki
    XWSS 3.0 https://xwss.dev.java.net/files/documents/4864/72021/xwss-3.0.zip
    WSIT https://jax-ws.dev.java.net/files/documents/4202/68724/wsit-1_0-fcs-bin-b26-31_jul_2007.jar

  2. Biblioteki wrzuciłem do lib (xwss-security.jar, webservices-api.jar, webservices-tools.jar, webservices-rt.jar).

    • biblioteki JAXWS RI
  3. Zmieniłem z przykładu SecurityHandler i SecurityEnvironmentHandler, tak by zajmowały się jedynie stroną serwera:

package ws.security;

import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.FileInputStream;
import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.SubjectAccessor;
import com.sun.xml.wss.XWSSProcessorFactory;
import com.sun.xml.wss.XWSSProcessor;
import com.sun.xml.wss.XWSSecurityException;

public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
	private final static String CONFIG = "user-pass-authenticate-server.xml";
    private XWSSProcessor sprocessor = null;
    
    /** Creates a new instance of SecurityHandler */
    public SecurityHandler() {
        FileInputStream serverConfig = null;
        try {
            //domyslna sciezka w tomcacie to TOMCAT_HOME\bin
            serverConfig = new java.io.FileInputStream(new java.io.File("../webapps/xwss-test/WEB-INF/"+CONFIG));
            //Create a XWSSProcessFactory.
            XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
            sprocessor = factory.createProcessorForSecurityConfiguration(serverConfig, new SecurityEnvironmentHandler());
            serverConfig.close();
        } catch (Exception e) {
            throw new RuntimeException("Nie można utworzyć Zabezpieczen\n:"+e.getMessage());
        }

    }
    
    public Set<QName> getHeaders(){
        return null;
    }
    public boolean handleFault(SOAPMessageContext messageContext) {
        return true;
    }

     public boolean handleMessage(SOAPMessageContext messageContext) {
        secureServer(messageContext);
        return true;
    }
    public void close(MessageContext messageContext) {}
    
    private void secureServer(SOAPMessageContext messageContext) {
        Boolean outMessageIndicator = (Boolean)        
        messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        SOAPMessage message = messageContext.getMessage();
        
        if (outMessageIndicator.booleanValue()) {
            // do nothing....
            return;
        } else {
             //verify the secured message.
            try{
                ProcessingContext context =  sprocessor.createProcessingContext(message);
                context.setSOAPMessage(message);
                SOAPMessage verifiedMsg= null;
                verifiedMsg= sprocessor.verifyInboundMessage(context);
                
                messageContext.setMessage(verifiedMsg);
            } catch (XWSSecurityException ex) {
                //create a Message with a Fault in it
                //messageContext.setMessage(createFaultResponse(ex));
                throw new WebServiceException("[XSSecurityExceptiom]Wystąpił błąd podczas wywołania metody: secureServer:\n"+ex.getMessage());
            } catch(Exception ex){
                throw new WebServiceException("Wystąpił błąd podczas wywołania metody: secureServer:\n"+ex.getMessage());
            }
        }
    }    

    private SOAPMessage createFaultResponse(XWSSecurityException ex) {
        return null;
    }
}
package ws.security;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;
import java.util.StringTokenizer;
import java.io.IOException;

public class SecurityEnvironmentHandler implements CallbackHandler {
   
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (int i=0; i < callbacks.length; i++) {
        	
            if (callbacks[i] instanceof PasswordValidationCallback) {
                PasswordValidationCallback cb = (PasswordValidationCallback) callbacks[i];
                
                if (cb.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
                    cb.setValidator(new PlainTextPasswordValidator());
                    
                } else if (cb.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
                    PasswordValidationCallback.DigestPasswordRequest request = (PasswordValidationCallback.DigestPasswordRequest) cb.getRequest();
                    String username = request.getUsername();
                    
                    if ("Username".equals(username)) {
                        request.setPassword("PassworD");
                        cb.setValidator(new PasswordValidationCallback.DigestPasswordValidator());
                    }
                }
                //-------------
            } else {
                throw new UnsupportedCallbackException(callbacks[i],"Nieobsługiwane wywołanie zwrotne.");
            }
        }//end of for
    }
    
     private class PlainTextPasswordValidator implements PasswordValidationCallback.PasswordValidator { 
        public boolean validate(PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {
            
            PasswordValidationCallback.PlainTextPasswordRequest plainTextRequest =
            (PasswordValidationCallback.PlainTextPasswordRequest) request;
            if ("Username".equals(plainTextRequest.getUsername()) && "PassworD".equals(plainTextRequest.getPassword())) {
                return true;
            }
            return false;
        }
    }
}
  1. Plik konfiguracyjny serwera user-pass-authenticate-server.xml pozostawiłem bez zmian:
<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config" dumpMessages="true" >
    <xwss:RequireUsernameToken passwordDigestRequired="false"/>
</xwss:SecurityConfiguration>
  1. Utworzyłem plik konfiguracyjny handlera:
<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
	<handler-chain>
		<handler>
			<handler-name>SecurityHandler</handler-name>
			<handler-class>ws.security.SecurityHandler</handler-class>
		</handler>
	</handler-chain>
</handler-chains>
  1. Kod Usługi Sieciowej
package ws;

import javax.annotation.Resource;
import javax.annotation.PostConstruct;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.HandlerChain;
import javax.xml.ws.WebServiceContext;
import javax.servlet.http.HttpSession;
import javax.xml.ws.handler.MessageContext;
import javax.servlet.http.HttpServletRequest;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.xml.ws.WebServiceException;
import javax.naming.NamingException;


@WebService
@HandlerChain( file="../shandler.xml") //shandler.xml jest w katalogu WEB-INF
public class XWSSHello {
 	@Resource
        private WebServiceContext wsContext;
       
	private HttpSession session = null;
	/*
	 *
	 */
	@WebMethod
	public String sayHello() {
		MessageContext mc = wsContext.getMessageContext();
        	session = ((HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST)).getSession();
        
		String msg = "Hello "+session.getId();
		return msg;
	}
}

0

Skoro mają tak samo ponazywane pakiety i klasy to zastanawia mnie czy RI nie ma domyślnie wpisanego gdzieś zabezpieczenia XWSS. Problem jest ciekawy. Podaj jeszcze linki do javadoców, bo sądzę że dokładnie prześledzenie co i jak się z sobą wiąże może wyjaśnić kilka kwestii.

0

W sumie wydaje mi się, że się troche zakręciłem. Nie tyle powinienem używać bibliotek JAXWS RI, do stawiania zabezpieczonego serweru, tylko Web Services Interoperability Technologies (WSIT).

Zatem oczywiste były by konflikty ;/

(Moje motto: Najpierw rób potem myśl, czasami się nie sprawdza)

1 użytkowników online, w tym zalogowanych: 0, gości: 1