SOAP WS があり、WS-Security ユーザー名トークンを追加する必要があります。サービスへのアクセスを許可または拒否するためにユーザー名と pwd を探して soapHeader を解析するサーバー側の SoapHandler (実装クラスに @HandlerChain(file="handler-chain.xml") に注釈を付ける) を実装しました。これは usernametoken セキュリティを処理する正しい方法ですか、それともより良い方法がありますか? 私のハンドラーは次のとおりです。
public class SecurityValidatorHandler は SOAPHandler を実装します{
private static final String WSSE_NS_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static final QName QNAME_WSSE_USERNAMETOKEN = new QName(WSSE_NS_URI, "UsernameToken");
private static final QName QNAME_WSSE_USERNAME = new QName(WSSE_NS_URI, "Username");
private static final QName QNAME_WSSE_PASSWORD = new QName(WSSE_NS_URI, "Password");
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean outbound = (Boolean) context
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if ((outbound != null) && (!outbound.booleanValue())) {
handleInboundMessage(context);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
System.out.println("Server : handleFault()......");
return true;
}
@Override
public void close(MessageContext context) {
System.out.println("Server : close()......");
}
@Override
public Set<QName> getHeaders() {
System.out.println("Server : getHeaders()......");
return null;
}
private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
try {
System.out.println("Generating exception");
SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
SOAPFault soapFault = soapBody.addFault();
soapFault.setFaultString(reason);
throw new SOAPFaultException(soapFault);
}
catch(SOAPException e) { }
}
private void handleInboundMessage(SOAPMessageContext context) {
String wsseUsername = null;
String wssePassword = null;
try {
SOAPHeader header = context.getMessage().getSOAPHeader();
Iterator<?> headerElements = header.examineAllHeaderElements();
while (headerElements.hasNext()) {
SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements
.next();
//System.out.println(headerElement.getActor() + " " + headerElement.getRole() + " " + headerElement.getValue());
if (headerElement.getElementName().getLocalName()
.equals("Security")) {
SOAPHeaderElement securityElement = headerElement;
Iterator<?> it2 = securityElement.getChildElements();
while (it2.hasNext()) {
Node soapNode = (Node) it2.next();
if (soapNode instanceof SOAPElement) {
SOAPElement element = (SOAPElement) soapNode;
QName elementQname = element.getElementQName();
if (QNAME_WSSE_USERNAMETOKEN.equals(elementQname)) {
SOAPElement usernameTokenElement = element;
wsseUsername = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_USERNAME);
wssePassword = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_PASSWORD);
System.out.println(wsseUsername);
System.out.println(wssePassword);
break;
}
}
if (wsseUsername != null) {
break;
}
if(!"mypwd".equalsIgnoreCase(wssePassword)){
generateSOAPErrMessage(context.getMessage(), "access denied");
}
}
}
context.put("USERNAME", wsseUsername);
context.setScope("USERNAME", Scope.APPLICATION);
context.put("PASSWORD", wssePassword);
context.setScope("PASSWORD", Scope.APPLICATION);
}
} catch (SOAPException e) {
System.out.println("Error reading SOAP message context: " + e);
e.printStackTrace();
}
}
private String getFirstChildElementValue(SOAPElement soapElement, QName qNameToFind) {
String value = null;
Iterator<?> it = soapElement.getChildElements(qNameToFind);
while (it.hasNext()) {
SOAPElement element = (SOAPElement) it.next(); //use first
value = element.getValue();
}
return value;
}
}
しかし、この方法では、チェックしようとすると機能しません
if (soapNode instanceof SOAPElement)
要素をキャストするためにSOAPElementのインスタンスではないため、ユーザー名とpwdを解析しません。どうすればこれを解決できますか? 前もって感謝します。