MonoTouch Web服务请求SSL获取的认证或解密失败“ [英] MonoTouch Web Service Request over SSL Gets 'authentication or decryption has failed'

查看:348
本文介绍了MonoTouch Web服务请求SSL获取的认证或解密失败“的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过SSL的Web服务请求在Monotouch v4.0.4.1上引发了WebException:

 写:认证或解密失败)'

由于服务器的SSL证书是自签名的btw我认为它不是X.509),我绕过使用ServicePointManager.ServerCertificateValidationCallback的证书验证。完全相同的代码在Windows .NET上正常工作,其中Web服务调用返回正确的结果。在Monotouch添加Writeline表明ServerCertificateValidationCallback委托代码永远不会到达。



注意:虽然可能不相关,请求的内容是SOAP与嵌入式WS安全UsernameToken


  1. 有没有人在MonoTouch上工作?已经看到类似症状但没有决议的报告。代码和stacktrace如下,任何评论赞赏。


  2. 我收集了一个替代方法,使用certmgr.exe将自签名服务器证书存储在本地信任存储,但似乎无法在MonoTouch发布中找到该应用程序。有人可以指点我吗?


..

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

//名称AppDelegate在MainWindow.xib文件中引用。
public partial class AppDelegate:UIApplicationDelegate
{
//当应用程序加载其UI并准备运行时调用此方法
public override bool FinishedLaunching(UIApplication app,NSDictionary选项)
{
//如果已定义视图,请在此处添加:
// window.AddSubview(navigationController.View);

string soapResponse;
string soapRequest = @SOAP信封在这里但为了简洁省略;
soapResponse = WebService.Invoke(myOperation,soapRequest);
window.MakeKeyAndVisible();
return true;
}

//此方法在iPhoneOS 3.0中是必需的
public override void OnActivated(UIApplication application)
{
}
}


public class WebService
{
public static string Invoke(string operation,string soapRequest)
//输入参数:
//操作= WS操作名称
// soapRequest = SOAP XML请求
//输出参数:
// SOAP XML响应
{
HttpWebResponse响应;
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback =(sender,cert,chain,ssl)=>真正;
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();
使用(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/\\\\
\txmlns:ns1 = \http:// mycompany / Common / Primitives / v1\\\\
\txmlns:ns2 = \http:// mycompany / Common / actions / externals / Order / v1\\\\
\txmlns:ns3 = \ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\\"> ;\\\
\t<SOAP-ENV:Header> < wsse:Security SOAP-ENV:mustUnderstand = \1 \\\\
\txmlns:wsse = \http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-wssecurity-secext-1.0.xsd \> \\\
\t< wsse:UsernameToken wsu:Id = \UsernameToken-1 \\\\
\txmlns:wsu = \ http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\\"> \\\
\t< wsse:Username> myusername< / wsse:Username>< wsse:Password \\\
\tType = \http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile- 1.0#PasswordText\> mypw< / wsse:Password> \\\
\t< wsse:Nonce> {0}< / wsse:Nonce> \\\
\t< wsu:Created xmlns:wsu = \http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\ > {1}< / wsu:Created> \\\
\t< / wsse:UsernameToken> < / wsse:Security> \\\
\t< / SOAP-ENV:Header>< SOAP-ENV:Body>< ns2:tp_getOrderDetailRequest>< ns2:header>< ns1:source> TEAM< / ns1:source> \\\
\t< ns1:userAccessKey> 12345678901234567< / ns1:userAccessKey>< / ns2:header> \\\
\t< ns2:OrderId> myid1< / ns2:OrderId> \\\
\t< ns2:OrderId> ; myid2< / ns2:OrderId> \\\
\t< / ns2:tp_getOrderDetailRequest> \\\
\t< / SOAP-ENV:Body> \\\
\t< / SOAP-ENV:Envelope>在/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


解决方案

MonoTouch(类似Mono)不支持TLS_DH *密码套件(如TLS_DHE_DSS_WITH_AES_128_CBC_SHA)。



当服务器配置为仅接受它们时,协商阶段提前很早就会失败(在客户端Hello后接收到来自服务器的警报



确保您的服务器允许更传统的密码套件,例如非常安全(但速度慢)TLS_RSA_WITH_AES_256_CBC_SHA或更快(非常常见)的密码套件:TLS_RSA_WITH_RC4_128_ [MD5 | SHA]和Mono [Touch]应该可以很好地使用它们。



请注意,这与SOAP或Web服务(甚至X.509证书)无关 - 它只是纯SSL。


A web service request over SSL raises a WebException on Monotouch v4.0.4.1:

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

Since the server's SSL certificate is self-signed (and btw I think it is not X.509), I am bypassing the certificate validation using ServicePointManager.ServerCertificateValidationCallback. The exact same code works fine on Windows .NET, where the web service call returns the correct result. On Monotouch adding a Writeline shows that the ServerCertificateValidationCallback delegate code is never reached.

Note: Although probably not relevant, the content of the request is SOAP with embedded WS-Security UsernameToken.

  1. Has anyone got something like this to work on MonoTouch? Have seen reports of similar symptom but no resolution. The code and stacktrace are below, any comment appreciated. Can email a self-contained test case if wanted.

  2. I gather there is an alternative approach using certmgr.exe to store the self-signed server certificate in the local trust store, but can't seem to find that app in the MonoTouch distribution. Could anyone point me to it?

..

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);
        }
    }
} 

Stack trace (some names changed to protect the innocent, original available on request):

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

解决方案

MonoTouch (just like Mono) does not support TLS_DH* cipher suites (like TLS_DHE_DSS_WITH_AES_128_CBC_SHA).

When a server is configured to accept only them then the negotiation stage fails very early (an Alert is received from the server after the Client Hello message is sent) which explains why the callback was never called.

Ensure your server allows the more traditional cipher suites, e.g. the very secure (but slow) TLS_RSA_WITH_AES_256_CBC_SHA or the faster (and very common) Cipher Suite: TLS_RSA_WITH_RC4_128_[MD5|SHA], and Mono[Touch] should work well using them.

Note that this is unrelated to SOAP or web-services (and even X.509 certificates) - it's just plain SSL.

这篇关于MonoTouch Web服务请求SSL获取的认证或解密失败“的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆