Защита веб-службы с помощью профиля UsernameToken 1.0 с использованием Axis2 и Rampart
Это мой первый вопрос по переполнению стека.
Я не опытный программист Java, но у меня есть предыдущий опыт работы с языком и различными IDE.
У меня есть сценарий, когда клиент требует, чтобы из заданного WSDl я создал службу, которая должна быть аутентифицирована с использованием DefaultToCen Profile 1.0 OASIS Standard 200401. Она будет защищена с помощью ssl на производственных серверах.
Я проводил некоторые исследования и пытался реализовать различные случаи, и я пришел к точке, где у меня ничего не работает должным образом.
Я использую:
- Затмение как базовая IDE
- Axis2 V1.6.3
- Rampart V1.6.2
- Rahas V1.6.2
Чтобы проиллюстрировать текущую ситуацию, здесь я покажу вам структуру, которую eclipse создает для меня при генерации структуры сервиса java bean из wsdl eclipse в качестве базовой IDE.
https://dl.dropboxusercontent.com/u/71031985/schema.png
применяемая конфигурация:
в WebContent/WEB-INF/conf/axis2.xml я включаю модуль rampart и passwordCallbackClass для обработки имени пользователя и пароля, указанных в заголовках мыла.
<module ref="rampart" />
<parameter name="InflowSecurity">
<action>
<items>UsernameToken</items>
<passwordCallbackClass>
serviceManager.ServiceAuthUserNameToken
</passwordCallbackClass>
<passwordType>PasswordText</passwordType>
</action>
</parameter>
...
В файле, расположенном в /WebContent/WEB-INF/services/ProveedorCentroTFWS/META-INF/services.xml, я размещаю политику rampart, чтобы выполнить требование usernametoken:
<wsp:Policy wsu:Id="UTOverTransport" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
</wsp:Policy>
</sp:TransportBinding>
<sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
</wsp:Policy>
</sp:SignedSupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordCallbackClass>serviceManager.ServiceAuthUserNameToken</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
При выполнении вызова от тестового клиента, предоставленного клиентом (и он не может быть изменен), он отправляет следующее мыльное сообщение:
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="UsernameToken-3">
<wsse:Username>username</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">definedpwd</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:To>http://localhost:8080/ProveedorCentroTFWS</wsa:To>
<wsa:MessageID>urn:uuid:f2fb54d9-8957-49a2-88a7-de6d209e6d35</wsa:MessageID>
<wsa:Action>getActionList</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ns3:getActionListxmlns:ns3="http://impl.ws.application.proveedorcentro.meyss.spee.es" />
</soapenv:Body>
После отправки сообщения мыла возвращается следующая ошибка:
java.lang.RuntimeException: Malformed uri: UsernameTokenPolicy
И след стека, который это следует:
org.apache.neethi.PolicyReference.getRemoteReferencedPolicy(PolicyReference.java:155)
org.apache.neethi.PolicyReference.normalize(PolicyReference.java:110)
org.apache.axis2.util.PolicyUtil.getMergedPolicy(PolicyUtil.java:267)
org.apache.axis2.description.AxisBindingMessage.calculateEffectivePolicy(AxisBindingMessage.java:294)
org.apache.axis2.description.AxisBindingMessage.getEffectivePolicy(AxisBindingMessage.java:225)
org.apache.axis2.context.MessageContext.getEffectivePolicy(MessageContext.java:1617)
org.apache.rampart.RampartMessageData.<init>(RampartMessageData.java:233)
org.apache.rampart.MessageBuilder.build(MessageBuilder.java:61)
org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:65)
org.apache.axis2.engine.Phase.invokeHandler(Phase.java:340)
org.apache.axis2.engine.Phase.invoke(Phase.java:313)
org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:262)
org.apache.axis2.engine.AxisEngine.sendFault(AxisEngine.java:516)
org.apache.axis2.transport.http.AxisServlet.handleFault(AxisServlet.java:433)
org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:216)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Я проверил все и вся, чтобы попытаться заставить его принимать мыльные сообщения, но я не могу заставить его работать.
спасибо за вашу поддержку и внимание
1 ответ
Решение этой проблемы заключается в том, что предоставляемый WSDL пропускает некоторые части, чтобы иметь возможность аутентификации в соответствии со стандартом UsernameToken Profile 1.0 OASIS 20040101.
Нашел решение для этого на странице IBM о WS-Security с Metro.
В документе WSDL под тегом привязки была ссылка на политику:
<wsp:PolicyReference URI="#UsernameTokenPolicy" wsdl:required="true"/>
Читая онлайн-документацию, я увидел, что она указывает на никуда, и необходимо добавить запись политики в тот же файл WSLD, что и следующий, имеющий идентификатор Name (#UsernameTokenPolicy) или желаемое имя политики, которую мы хотим применить:
<wsp:Policy wsu:Id="UsernameTokenPolicy" xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsss:Validator name="usernameValidator" classname="[packageName].[callBackValidatorName]"/>
</wsss:ValidatorConfiguration>
</wsp:Policy>
После того, как это будет сделано, вам нужно создать Validator обратного вызова с ответом для обработки учетных данных заголовка запроса SOAP, как показано в следующем примере:
package [packageName];
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class [callBackValidatorName] implements PasswordValidationCallback.PasswordValidator{
@Override
public boolean validate(PasswordValidationCallback.Request request) throws PasswordValidationCallback.PasswordValidationException {
PasswordValidationCallback.PlainTextPasswordRequest ptreq;
ptreq = (PasswordValidationCallback.PlainTextPasswordRequest) request;
return "[HARCODED_USERNAME]".equals(ptreq.getUsername()) &&
"[HARCODED_PWD]".equals(ptreq.getPassword());
}
}
После того как все это будет сделано, вы должны иметь возможность аутентифицировать сообщение SOAP, которое соответствует UsernameToken Profile 1.0 OASIS Standard 200401, в веб-сервисе Java на стороне сервера.