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:
-
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 -
Biblioteki wrzuciłem do lib (xwss-security.jar, webservices-api.jar, webservices-tools.jar, webservices-rt.jar).
- biblioteki JAXWS RI
-
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;
}
}
}
- 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>
- 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>
- 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;
}
}