MonoTouch Web Service Request через SSL Получает «аутентификация или дешифрование не удалось» - PullRequest
2 голосов
/ 03 августа 2011

Запрос веб-службы по SSL вызывает исключение WebException в Monotouch v4.0.4.1:

'Error getting response stream (Write: The authentication or decryption has failed)'

Поскольку SSL-сертификат сервера является самоподписанным (и, кстати, я думаю, что это не X.509), я обошел проверку сертификата с помощью ServicePointManager.ServerCertificateValidationCallback. Точно такой же код прекрасно работает в Windows .NET, где вызов веб-службы возвращает правильный результат. При Monotouch добавление Writeline показывает, что код делегата ServerCertificateValidationCallback никогда не достигается.

Примечание. Хотя, возможно, это и не актуально, содержимое запроса является SOAP со встроенным WS-Security UsernameToken.

  1. У кого-нибудь есть что-то подобное для работы в MonoTouch? Видел сообщения о подобном симптоме, но без разрешения. Код и трассировка стека находятся ниже, любой комментарий приветствуется. При желании можете отправить по электронной почте отдельный тестовый пример.

  2. Я понимаю, что существует альтернативный подход, использующий certmgr.exe для хранения самоподписанного сертификата сервера в локальном хранилище доверенных сертификатов, но, похоже, не могу найти это приложение в дистрибутиве MonoTouch. Кто-нибудь может указать мне на это?

..

public class Application
{
    static void Main (string[] args)
    {
        UIApplication.Main (args);
    }
}

// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
    // This method is invoked when the application has loaded its UI and its ready to run
    public override bool FinishedLaunching (UIApplication app, NSDictionary options)
    {
        // If you have defined a view, add it here:
        // window.AddSubview (navigationController.View);

        string soapResponse;
        string soapRequest = @" SOAP envelope is here but omitted for brevity ";
        soapResponse = WebService.Invoke("myOperation", soapRequest);
        window.MakeKeyAndVisible ();
        return true;
    }

    // This method is required in iPhoneOS 3.0
    public override void OnActivated (UIApplication application)
    {
    }
}


public class WebService
{
    public static string Invoke(string operation, string soapRequest)
     // Input parameters: 
    //  operation = WS operation name
    //  soapRequest = SOAP XML request
    // Output parameter:
    //  SOAP XML response
    {
        HttpWebResponse response;
        try
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, ssl) => true;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myserver.com:7570/MyEndpoint");
            request.Method = "POST";
            request.Headers.Add("SOAPAction", "/MyEndpoint/" + operation);
            request.ContentType = "text/xml;charset=UTF-8";
            request.UserAgent = "Smartphone";
            request.ContentLength = soapRequest.Length;
            request.GetRequestStream().Write(System.Text.Encoding.UTF8.GetBytes(soapRequest), 0, soapRequest.Length);
            request.GetRequestStream().Close();
            response = (HttpWebResponse)request.GetResponse();
            using (StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8))
            {
                return reader.ReadToEnd();
            }
        }
        catch (WebException e)
        {
            throw new WebException(e.Message);
        }
    }
} 

Трассировка стека (некоторые имена изменены для защиты невинных, оригинал доступен по запросу):

WS.WebService.Invoke (operation="myOperation", soapRequest="<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" \n\txmlns:ns1=\"http://mycompany/Common/Primitives/v1\" \n\txmlns:ns2=\"http://mycompany/Common/actions/externals/Order/v1\" \n\txmlns:ns3=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">\n\t<SOAP-ENV:Header> <wsse:Security SOAP-ENV:mustUnderstand=\"1\" \n\txmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"> \n\t<wsse:UsernameToken wsu:Id=\"UsernameToken-1\" \n\txmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\"> \n\t<wsse:Username>myusername</wsse:Username> <wsse:Password \n\tType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">mypw</wsse:Password> \n\t<wsse:Nonce>{0}</wsse:Nonce> \n\t<wsu:Created xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">{1}</wsu:Created> \n\t</wsse:UsernameToken> </wsse:Security> \n\t</SOAP-ENV:Header><SOAP-ENV:Body><ns2:tp_getOrderDetailRequest><ns2:header><ns1:source>TEAM</ns1:source>\n\t<ns1:userAccessKey>12345678901234567</ns1:userAccessKey></ns2:header>\n\t<ns2:OrderId>myid1</ns2:OrderId>\n\t<ns2:OrderId>myid2</ns2:OrderId>\n\t</ns2:tp_getOrderDetailRequest>\n\t</SOAP-ENV:Body>\n\t</SOAP-ENV:Envelope>") in /Users/billf/Projects/WS/WS/Main.cs:103
WS.AppDelegate.FinishedLaunching (app={MonoTouch.UIKit.UIApplication}, options=(null)) in /Users/billf/Projects/WS/WS/Main.cs:52
MonoTouch.UIKit.UIApplication.Main (args={string[0]}, principalClassName=(null), delegateClassName=(null)) in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:26
MonoTouch.UIKit.UIApplication.Main (args={string[0]}) in /Developer/MonoTouch/Source/monotouch/monotouch/UIKit/UIApplication.cs:31
WS.Application.Main (args={string[0]}) in /Users/billf/Projects/WS/WS/Main.cs:18

Ответы [ 2 ]

2 голосов
/ 05 августа 2011

MonoTouch (как и Mono) не поддерживает наборы шифров TLS_DH * (например, TLS_DHE_DSS_WITH_AES_128_CBC_SHA).

Когда сервер настроен на прием только их, этап согласования завершается неудачно очень рано (с сервера отправляется предупреждение после отправки сообщения Client Hello), что объясняет, почему обратный вызов никогда не вызывался.

Убедитесь, что ваш сервер поддерживает более традиционные наборы шифров, например, очень безопасный (но медленный) TLS_RSA_WITH_AES_256_CBC_SHA или более быстрый (и очень распространенный) набор шифров: TLS_RSA_WITH_RC4_128_ [MD5 | SHA], и Mono [Touch] должен хорошо работать с ними.

Обратите внимание, что это не связано с SOAP или веб-сервисами (и даже сертификатами X.509) - это просто простой SSL.

2 голосов
/ 03 августа 2011

1) Ненадежный корневой сертификат - не единственная проблема, которая может привести к этому исключению.

ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, ssl) => true;

Добавьте туда Console.WriteLine, чтобы увидеть, вызывается ли он (или нет)..

throw new WebException(e.Message);

и еще один здесь, с полной трассировкой стека (не только свойство Message).

2) Каждое приложение является изолированным.Это означает, что:

  • приложения не могут обновлять глобальные хранилища сертификатов iOS (что может создать проблемы с безопасностью);

  • , если существует инструмент certmgr (для MT) он может использовать только локальное (моно) хранилище, которое можно будет использовать только для него самого (что не поможет в ваших собственных приложениях)

...