Mam załóżmy prosty serwer, autoryzujący w oparciu o jedną nazwe użytkownika i hasło:
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 java.io.File;
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;
import java.util.HashSet;
public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
private final static String CFG_PATH = "../webapps/xhell/WEB-INF/server/cfg";
private final static String CONFIG = "user-pass-authenticate-server.xml";
private XWSSProcessor processor = null;
public SecurityHandler() {
FileInputStream serverConfig = null;
try {
serverConfig = new FileInputStream(new File(CFG_PATH+"/"+CONFIG));
XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
processor = factory.createProcessorForSecurityConfiguration(serverConfig, new ServerSecurityEnvironmentHandler());
serverConfig.close();
} catch (Exception e) {
throw new RuntimeException("[SERWER]: Błąd! Nie można utworzyć SecurityHandler:\n"+e.getMessage());
}
}
public Set<QName> getHeaders(){
QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "");
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}
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;
outMessageIndicator= (Boolean)messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage message = messageContext.getMessage();
if (outMessageIndicator.booleanValue())
return;
try{
ProcessingContext context = processor.createProcessingContext(message);
context.getExtraneousProperties().putAll(messageContext);
context.setSOAPMessage(message);
SOAPMessage verifiedMsg= null;
verifiedMsg= processor.verifyInboundMessage(context);
messageContext.setMessage(verifiedMsg);
} catch (Exception ex) {
throw new WebServiceException("[SERWER]: Błąd autoryzacji!");
}
}
}
package ws.security;
import java.io.IOException;
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.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class ServerSecurityEnvironmentHandler implements CallbackHandler {
private final static String USERNAME = "Username";
private final static String PASSWORD = "PassworD";
public void handle(Callback[] call) throws IOException, UnsupportedCallbackException {
for(int i=0; i<call.length; i++) {
if(call[i] instanceof PasswordValidationCallback) { //passwordValidation
PasswordValidationCallback passCallback = (PasswordValidationCallback)call[i];
if(passCallback.getRequest() instanceof PasswordValidationCallback.PlainTextPasswordRequest) {
passCallback.setValidator(new PlainTextPasswordValidator());
} else if(passCallback.getRequest() instanceof PasswordValidationCallback.DigestPasswordRequest) {
PasswordValidationCallback.DigestPasswordRequest request;
request = (PasswordValidationCallback.DigestPasswordRequest)passCallback.getRequest();
String username = request.getUsername();
if(USERNAME.equals(username)) {
request.setPassword(PASSWORD);
passCallback.setValidator(new PasswordValidationCallback.DigestPasswordValidator());
}
}
} else {
throw new UnsupportedCallbackException(call[i],"[SERWER]: Błąd! Nieobługiwane wywołanie zwrotne");
}
}
}
private class PlainTextPasswordValidator implements PasswordValidationCallback.PasswordValidator {
public boolean validate(PasswordValidationCallback.Request request)
throws PasswordValidationCallback.PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest plain;
plain = (PasswordValidationCallback.PlainTextPasswordRequest)request;
if(USERNAME.equals(plain.getUsername()) && PASSWORD.equals(plain.getPassword()))
return true;
return false;
}
}
}
package ws;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.HandlerChain;
import javax.annotation.Resource;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
@WebService
@HandlerChain(file="../server/cfg/handler.xml")
public class XHello {
@Resource
private WebServiceContext wsContext;
@WebMethod
public String sayHello(String name) {
return "Hello: "+name;
}
}
Teraz chciałbym w metodzie sayHello, odczytać nazwę użytkownika, która była sprawdzana w ServerSecurityEnvironmentHandler.
Serwer działa pod Tomcatem