GVKun编程网logo

c# – Xamarin中的WebException,使用HttpClient(.net xamarin)

24

本文将分享c#–Xamarin中的WebException,使用HttpClient的详细内容,并且还将对.netxamarin进行详尽解释,此外,我们还将为大家带来关于AndroidHttpClie

本文将分享c# – Xamarin中的WebException,使用HttpClient的详细内容,并且还将对.net xamarin进行详尽解释,此外,我们还将为大家带来关于Android HttpClient:NetworkOnMainThreadException、android – 使用loopj SyncHttpClient时的IOException、Apache HTTPClient SSLPeerUnverifiedException、Apache HttpClient临时错误:NoHttpResponseException的相关知识,希望对你有所帮助。

本文目录一览:

c# – Xamarin中的WebException,使用HttpClient(.net xamarin)

c# – Xamarin中的WebException,使用HttpClient(.net xamarin)

我正在学习如何在C#中使用xamarin,并且我有一个 Android应用程序来向外部API发出Web请求,并且我收到以下错误;
System.Net.Http.HttpRequestException: An error occurred while sending the 
request ---> System.Net.WebException: Error: SecureChannelFailure (The   
authentication or decryption has Failed.) ---> System.IO.IOException: The 
authentication or decryption has Failed. ---> System.IO.IOException: The 
authentication or decryption has Failed. ---> 
Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has Failed.

我的代码如下;

public async Task<List<T>> GetList<T>(string url)
    {
        HttpClient client = new HttpClient();
        var response = await client.GetAsync(new Uri(url));
        response.EnsureSuccessstatusCode();
        var content = await response.Content.ReadAsstringAsync();
        return JsonConvert.DeserializeObject<List<T>>(content);
    }

android中的MainClass调用核心类,它调用此服务类.

当API不使用HTTPS时,HttpClient请求会起作用,但每当我使用启用了HTTPS的API时,都会抛出此错误.

我也使用可移植类库来存储代码,因此无法使用HttpWebRequest进行Web请求.

我也尝试过;

ServicePointManager.ServerCertificateValidationCallback += (o,certificate,chain,errors) => true;

和;

System.Security.Cryptography.AesCryptoServiceProvider b = new System.Security.Cryptography.AesCryptoServiceProvider();

在我的应用程序OnCreate类(android)中.

我还将HttpClient实现更改为AndroidClientHandler,同时将SSL / TLS实现更改为1.1.在模拟器和设备上尝试此操作.

有人有建议吗?

解决方法

试试这个:
打开Android项目属性 – > Android选项 – >高级

将HttpClient实现设置从Default切换到Android

似乎默认的Mono客户端处理程序因HTTPS而中断.

Android HttpClient:NetworkOnMainThreadException

Android HttpClient:NetworkOnMainThreadException

我在下面有一些代码:

protected void testConnection(String url) {
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet(url);
    ResponseHandler<String> responsehandler = new BasicResponseHandler();

    try {
        String connection = httpclient.execute(httpget, responsehandler);
        Toast.makeText(getBaseContext(), R.string.connection_succeed, Toast.LENGTH_SHORT).show();
        view_result.setText(connection);
    } catch(IOException e) {
        Toast.makeText(getBaseContext(), R.string.connection_Failed, Toast.LENGTH_SHORT).show();
    }
    httpclient.getConnectionManager().shutdown();
}

并在Menifest中添加权限:

<uses-permission android:name="android.permission.INTERNET"/>

但它是一个例外:
networkonmainthreadException,
我能怎么做?

解决方法:

在ICS及更高版本上,您无法再在UI线程上执行网络操作.相反,你被迫创建一个新的线程并在那里做你的网络.

可能的工具是Android的AsyncTask和普通的Java Thread.

可以在这里找到一个很好的教程:Android Threads, Handlers and AsyncTask – Tutorial

android – 使用loopj SyncHttpClient时的IOException

android – 使用loopj SyncHttpClient时的IOException

我需要在几个区域使用loopj的SyncHttpClient.当我使用AsyncHttpClient时,请求成功返回.当我使用SyncHttpClient时,如此处接受的答案所示:How to use loopJ SyncHttpClient for synchronous calls?,我在onFailure中遇到了一个断点. statusCode为0,errorResponse为null,throwable为java.io.IOException:未处理的异常:null.

这是相关的代码.我再次使用Async时效果很好:

        buttonTest.setonClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                AsyncHttpClient httpClient = new AsyncHttpClient();
                SyncHttpClient httpClient = new SyncHttpClient();

                httpClient.get("http://10.0.1.6:3000/home/test_endpoint", new JsonHttpResponseHandler() {
                    @Override
                    public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
                        String stringResponse = response.toString();
                    }

                    @Override
                    public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
                        String error = errorResponse.toString();
                    }
                });

                String temp = "got here";
            }
        });

我正在使用编译’com.loopj.android:android-async-http:1.4.9′

解决方法:

当我点击这个时我做了一些调试,我发现loopj正在吃以下异常:

android.os.networkonmainthreadException

我无法提供详细的堆栈跟踪,因为这个异常似乎没有正确记录(由于某些原因,logcat根本没有提取它)

但是,它位于这里:

AsyncHttpRequest.makeRequestWithRetries(AsyncHttpRequest.java:203)

我一直在运行我的代码:

Handler handler = new Handler();
Runnable r = new Runnable(){
  public void run(){
    SyncHttpClient client ....
    client.get(.....); // hit error here
  }
};

正如您所看到的,我碰巧在Handler.post()方法中运行我的SyncHttpClient,但显然实现不算作(非主线程上的网络)

修复它的关键是使用了mikeorr85的代码所包含的“新线程(…)”.像这样……

new Thread(Runnable r = new Runnable(){
  public void run(){
    SyncHttpClient client ....
    client.get(.....); // hit error here
  }
}).start();

Apache HTTPClient SSLPeerUnverifiedException

Apache HTTPClient SSLPeerUnverifiedException

使用Apache HttpClient 4.2.1。使用从基于表单的登录示例复制的代码

http://hc.apache.org/httpcomponents-client-
ga/examples.html

访问受SSL保护的登录表单时出现异常:

Getting library items from https://appserver.gtportalbase.com/agileBase/AppController.servlet?return=blankjavax.net.ssl.SSLPeerUnverifiedException: peer not authenticatedClosing http connectionat sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572)at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640)at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)

据我所知,该证书很好(请参阅堆栈跟踪之前的URL),并且不会过期-浏览器不会抱怨。

我尝试将证书导入到我的密钥库中

如何使用Apache
HttpClient处理无效的SSL证书?

没有变化。我相信您可以创建一个自定义SSLContext来强制Java忽略该错误,但是我宁愿解决根本原因,因为我不想打开任何安全漏洞。

有任何想法吗?

答案1

小编典典

编辑 我知道这个答案很久以前就被接受了,并且也被投票了3次,但这是(至少部分是)错误的,所以这里有更多关于此异常的信息。不便之处敬请原谅。

javax.net.ssl.SSLPeerUnverifiedException:对等方未通过身份验证

当远程服务器根本不发送证书时, 通常会 抛出此异常。但是,由于在此版本sun.security.ssl.SSLSocketImpl.getSession()中实现的方式以及实现的方式,因此在使用Apache HTTP
Client时会遇到一些极端情况。

当使用Apache HTTP Client时,当不信任远程证书时也会抛出该异常,这通常会抛出“
sun.security.validator.ValidatorException: PKIX path building failed”。

发生这种情况的原因是因为Apache HTTP Client SSLSession在执行其他操作之前会尝试获取和对等证书。

提醒一下,有3种方法可以通过发起握手SSLSocket

  • 调用开始显式开始握手的startHandshake,或
  • 尝试在此套接字上读取或写入应用程序数据会导致隐式握手,或者
  • 如果当前没有有效的会话,则对getSession的调用尝试建立会话,并且隐式握手已完成。

这是3个示例,所有示例均针对具有不可信证书的主机(使用javax.net.ssl.SSLSocketFactory,而不是Apache)。

范例1:

    SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory();    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example",            443);    sslSocket.startHandshake();

这将引发“ javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException: PKIX path building failed”(如预期)。

范例2:

    SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory();    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example",            443);    sslSocket.getInputStream().read();

这也会引发“ javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException: PKIX path building failed”(如预期)。

范例3:

    SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory();    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example",            443);    SSLSession sslSession = sslSocket.getSession();    sslSession.getPeerCertificates();

但是,这引发了javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

这是Apache
HTTP客户端AbstractVerifierorg.apache.http.conn.ssl.SSLSocketFactory在4.2.1版中使用的逻辑。更高版本基于发出的HTTPCLIENT-1346报告显式调用startHandshake()

最终,这似乎来自的实现sun.security.ssl.SSLSocketImpl.getSession(),该实现捕获了IOException在调用startHandshake(false)(内部方法)时抛出的潜在s
,而没有进一步抛出它。这可能是一个错误,尽管这不会对安全产生重大影响,因为SSLSocket无论如何仍将关闭。

范例4:

    SSLSocketFactory ssf = (SSLSocketFactory) sslContext.getSocketFactory();    SSLSocket sslSocket = (SSLSocket) ssf.createSocket("untrusted.host.example",            443);    SSLSession sslSession = sslSocket.getSession();    // sslSession.getPeerCertificates();    sslSocket.getInputStream().read();

值得庆幸的是,javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException: PKIX path buildingfailed每当您实际尝试使用它时,它仍然会抛出“ ” SSLSocket(在没有获得对等证书的情况下获得会话不会造成漏洞)。


如何解决这个问题

像其他任何不信任的证书问题一样,确保您使用的信任库包含必要的信任锚(例如,颁发要尝试验证的链的CA证书,或者可能是实际服务器)特殊情况证书)。

要解决此问题,您应该将CA证书(或者可能是服务器证书本身)导入到信任库中。你可以这样做:

  • 在您的JRE信任库中,通常是cacerts文件(不一定是最好的文件,因为这会影响使用该JRE的所有应用程序),
  • 在您的信任库的本地副本中(您可以使用-Djavax.net.ssl.trustStore=...选项进行配置),
  • 通过SSLContext为该连接创建一个特定对象。(有人建议使用不执行任何操作的信任管理器,但这会使您的连接容易受到MITM攻击。)

初步答案

javax.net.ssl.SSLPeerUnverifiedException:对等方未通过身份验证

这与信任证书无关,或者您必须创建一个自定义SSLContext:这是由于服务器根本不发送任何证书。

显然,该服务器未配置为正确支持TLS。这将失败(您将不会获得远程证书):

openssl s_client -tls1 -showcerts -connect

appserver.gtportalbase.com:443

但是,SSLv3似乎可以工作:

openssl s_client -ssl3 -showcerts -connect

appserver.gtportalbase.com:443

如果您知道谁在运行此服务器,则值得与他们联系以解决此问题。至少现在,服务器应该真正支持TLSv1。

同时,解决此问题的一种方法是创建您自己的问题并将org.apache.http.conn.ssl.SSLSocketFactory其用于与Apache
Http客户端的此连接。

该工厂需要创建一个SSLSocket照常使用的方法sslSocket.setEnabledProtocols(new String[]{"SSLv3"});,以在返回该套接字之前使用它来禁用TLS,否则默认情况下将启用它。

Apache HttpClient临时错误:NoHttpResponseException

Apache HttpClient临时错误:NoHttpResponseException

我有一个Web服务正在接受XML的POST方法。它工作正常,然后在某个随机的时刻,它无法与服务器通信,并抛出message,并抛出IOException
The target server failed to respond。后续调用工作正常。

当我打了一些电话然后将应用程序闲置大约10-15分钟时,它就会发生。在此之后我进行的第一个调用将返回此错误。

我尝试了几件事…

我像这样设置重试处理程序

HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() {            public boolean retryRequest(IOException e, int retryCount, HttpContext httpCtx) {                if (retryCount >= 3){                    Logger.warn(CALLER, "Maximum tries reached, exception would be thrown to outer block");                    return false;                }                if (e instanceof org.apache.http.NoHttpResponseException){                    Logger.warn(CALLER, "No response from server on "+retryCount+" call");                    return true;                }                return false;            }        };        httpPost.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryHandler);

但是此重试从未被调用过。(是的,我正在使用正确的instanceof子句)。在调试时,此类永远不会被调用。

我什至尝试设置HttpProtocolParams.setUseExpectContinue(httpClient.getParams(),false);但没有用。有人可以建议我现在可以做什么吗?

重要事项 除了弄清楚为什么我会得到例外,我还有一个重要的担忧是为什么重试处理程序不在这里工作?

答案1

小编典典

由连接管理器保持活动状态的最有可能的持久连接变得陈旧。也就是说,目标服务器会在其连接空闲时关闭其末端的连接,而HttpClient无法对该事件做出反应,从而使连接半关闭或“陈旧”。通常这不是问题。HttpClient使用多种技术来验证从池中租借时的连接有效性。即使禁用了过时的连接检查并且使用了过时的连接来传输请求消息,请求执行通常也会在具有SocketException的写操作中失败,并会自动重试。但是,在某些情况下,写操作可以毫无例外地终止,随后的读操作将返回-1(流的结尾)。

解决此问题的最简单方法是将过期的连接和闲置了超过一段时间(例如,在池中闲置一分钟之后)之后空闲的连接驱逐出去。有关详细信息,请参见HttpClient教程的本节。

今天关于c# – Xamarin中的WebException,使用HttpClient.net xamarin的介绍到此结束,谢谢您的阅读,有关Android HttpClient:NetworkOnMainThreadException、android – 使用loopj SyncHttpClient时的IOException、Apache HTTPClient SSLPeerUnverifiedException、Apache HttpClient临时错误:NoHttpResponseException等更多相关知识的信息可以在本站进行查询。

本文标签: