Как использовать веб-службу Java Metro с использованием аутентификации по имени пользователя с помощью симметричного ключа в клиенте Gsoap? - PullRequest
1 голос
/ 12 марта 2012

Я занимаюсь исследованием взаимодействия между безопасными веб-сервисами.Безопасность должна быть сделана ТОЛЬКО на уровне сообщений.До сих пор мне удалось заставить WCF и WSIT / Metro работать вместе, используя сертификаты.Теперь я пытаюсь сделать то же самое с помощью gSoap, но пока мне не повезло.

Мне удалось создать файл заголовка из службы WSDL Java с помощью wsdl2h, и я смог сгенерироватьнеобходимые классы с использованием soapcpp2.Следуя документации по gsoap, подключаемые модули WSSE и WSA должны быть настроены правильно, и, действительно, если я провожу анализ кода в Wireshark, я вижу, что клиент Gsoap отправляет запрос с заголовком безопасности и полями WS-Addressing.(To, Action, MessageID, ReplyTo).

Служба Java настроена на использование аутентификации имени пользователя с помощью симметричного ключа с использованием алгоритма 3DES, токена аутентификации имени пользователя и макета заголовка безопасности Lax.

Сертификаты находятся в хранилище ключей Glassfish и в хранилище доверенных сертификатов ибыли экспортированы и преобразованы в PEM-файлы для использования в gSoap.

Это мой код для приложения C ++:

    #include <cstdlib>
    #include <iostream>
    #include "soapNewWebServicePortBindingProxy.h"
    #include "NewWebServicePortBinding.nsmap"
    #include "wsseapi.h"
    #include "wsaapi.h"

    using namespace std;

    /*
     * 
     */
    int main(int argc, char** argv) {
        static char DES_KEY[20] =
        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
        /* SET UP */
        NewWebServicePortBinding proxy;
        proxy.soap = soap_new1(SOAP_XML_CANONICAL | SOAP_XML_INDENT);
        soap_register_plugin(proxy.soap, soap_wsa);
        soap_register_plugin(proxy.soap, soap_wsse);  
        ns1__hello req;
        ns1__helloResponse resp;
        req.name = new std::string("derpenstein");  

        /* ADD WS-SECURITY ELEMENTS  */    
        soap_wsse_add_Security(proxy.soap);
        soap_wsse_add_Signature(proxy.soap);
        soap_wsse_add_Timestamp(proxy.soap, NULL, 300);

        //OpenSSL_add_all_algorithms();
        FILE *fd = fopen("gsoappublic.pem", "r");
        FILE *fpriv = fopen("gsoapprivate.pem", "r");

        X509 *cert = PEM_read_X509(fd, NULL, NULL, NULL);

        EVP_PKEY *privkey = NULL;
        EVP_PKEY *pubkey = NULL;

        privkey = PEM_read_PrivateKey(fpriv, NULL, NULL, (void*)"changeit");

        if (!privkey) {
            cout << "error getting private key" << endl;
            ERR_print_errors_fp(stderr);
            return -1;
        }

        pubkey = X509_get_pubkey(cert);
        if (!pubkey) {
            cout << "error getting public key from certificate" << endl;
        }
        fclose(fd);
        fclose(fpriv);

        if (soap_wsse_encrypt_body(proxy.soap, SOAP_MEC_ENC_DES_CBC, DES_KEY, sizeof(DES_KEY))
         || soap_wsse_add_EncryptedKey(proxy.soap, "Cert", cert, NULL)
         || soap_wsse_add_UsernameTokenText(proxy.soap, "User", "test", "test")
         || soap_wsse_sign_body(proxy.soap, SOAP_SMD_SIGN_RSA_SHA1, privkey, 0)
         || soap_wsse_add_BinarySecurityTokenX509(proxy.soap, "X509Token", cert)
         || soap_wsse_add_KeyInfo_SecurityTokenReferenceX509(proxy.soap, "#X509Token")){
            soap_print_fault(proxy.soap, stderr);
        }

        /* ADD WS-ADDRESSING */
        soap_wsse_set_wsu_id(proxy.soap, "wsa5:From wsa5:To wsa5:ReplyTo wsa5:FaultTo wsa5:Action");  
        if (soap_wsa_request(proxy.soap, "uuid:5012354ad", "http://belgianguypc:8080/NewSecureService/NewWebService", "http://newsec.mince.org/NewWebService/helloRequest")
            || soap_wsa_add_ReplyTo(proxy.soap, "http://www.w3.org/2005/08/addressing/anonymous")) {
            soap_print_fault(proxy.soap, stderr);
        }


        /* MAKE THE CALL */
        int err = proxy.__ns1__hello(&req, &resp);
        if (err == SOAP_OK) {
            cout << "Success!";
            cout << resp.return_;
        }
        else {
            cout << "When sending:" << endl;
            soap_print_fault(proxy.soap, stderr);
            return -1;
        }

        return 0;
    }

Насколько я знаю, то, что я делаю, добавляетметка времени, сертификат, имя пользователя и пароль, затем я шифрую тело с помощью фиктивного ключа DES и подписываю сообщение своим собственным закрытым ключом.Затем я делаю вызов ...

Однако это не работает, в результате я получаю следующее:

When sending:
SOAP 1.1 Fault: wsse:FailedCheck [no subcode]
"WSS1927: Error occurred while decrypting EncryptedKey"
Detail: [no detail]

GlassFish выдает трассировку стека:

SEVERE: WSS1913: Key used to decrypt EncryptedKey cannot be null
SEVERE: WSS1927: Error occured while decrypting EncryptedKey
SEVERE: WSITPVD0035: Error in Verifying Security in Inbound Message.
com.sun.xml.wss.impl.WssSoapFaultException: WSS1927: Error occured while decrypting EncryptedKey
    at com.sun.xml.ws.security.opt.impl.util.SOAPUtil.newSOAPFaultException(SOAPUtil.java:158)
    at com.sun.xml.ws.security.opt.impl.incoming.EncryptedKey.getKey(EncryptedKey.java:354)
    at com.sun.xml.ws.security.opt.impl.incoming.KeySelectorImpl.resolveDirectReference(KeySelectorImpl.java:628)
    at com.sun.xml.ws.security.opt.impl.incoming.processor.SecurityTokenProcessor.processDirectReference(SecurityTokenProcessor.java:267)
    at com.sun.xml.ws.security.opt.impl.incoming.processor.SecurityTokenProcessor.resolveReference(SecurityTokenProcessor.java:143)
    at com.sun.xml.ws.security.opt.impl.incoming.processor.KeyInfoProcessor.processKeyInfo(KeyInfoProcessor.java:152)
    at com.sun.xml.ws.security.opt.impl.incoming.processor.KeyInfoProcessor.getKey(KeyInfoProcessor.java:132)
    at com.sun.xml.ws.security.opt.impl.incoming.EncryptedData.process(EncryptedData.java:156)
    at com.sun.xml.ws.security.opt.impl.incoming.EncryptedData.<init>(EncryptedData.java:113)
    at com.sun.xml.ws.security.opt.impl.incoming.SecurityRecipient.createMessage(SecurityRecipient.java:791)
    at com.sun.xml.ws.security.opt.impl.incoming.SecurityRecipient.validateMessage(SecurityRecipient.java:232)
    at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.verifyInboundMessage(WSITServerAuthContext.java:586)
    at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.validateRequest(WSITServerAuthContext.java:360)
    at com.sun.xml.wss.provider.wsit.WSITServerAuthContext.validateRequest(WSITServerAuthContext.java:263)
    at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:173)
    at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:144)
    at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
    at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:641)
    at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:600)
    at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:585)
    at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:482)
    at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:314)
    at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:608)
    at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:259)
    at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:162)
    at org.glassfish.webservices.JAXWSServlet.doPost(JAXWSServlet.java:145)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:232)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: Key used to decrypt EncryptedKey cannot be null
    at com.sun.xml.ws.security.opt.impl.enc.CryptoProcessor.decryptKey(CryptoProcessor.java:346)
    at com.sun.xml.ws.security.opt.impl.incoming.EncryptedKey.getKey(EncryptedKey.java:351)
    ... 51 more

Полагаю, корень проблемы в том, что EncryptedKey является нулевым в соответствии с сервисом, но я не знаю, какой это будет ключ или почему он будет нулевым.

Итак, мой вопрос: возможно лииспользовать безопасный сервис Metro из Gsoap, если да, что я делаю не так?Чего мне не хватает?

Спасибо!

1 Ответ

0 голосов
/ 25 октября 2012

Вы пытались задать свой вопрос в группе gSOAP Yahoo?Это на http://tech.groups.yahoo.com/group/gsoap/. Нет обещаний;Я борюсь с подобной проблемой (другой сервис, но gSOAP для Java Apache Axis с WSSE), и мне немного помогли из этой группы.включить возврат полных сообщений об ошибках вместо строки «no detail».Это в этом сообщении: http://tech.groups.yahoo.com/group/gsoap/message/19031

...