【问题标题】:Android SSL HttpGet (No peer certificate) error OR (Connection closed by peer) errorAndroid SSL HttpGet(无对等证书)错误或(对等连接已关闭)错误
【发布时间】:2013-05-19 04:03:19
【问题描述】:

我正在尝试做一个简单的 HttpGet 来阅读网页。我在 iOS 和 Android 上通过 http 工作,但不是 https。

url是内部网络IP和自定义端口,所以我可以像这样使用http://ipaddress:port/MyPage.html的路径读取http

HttpClient httpclient = new DefaultHttpClient(httpParameters);
                    HttpResponse response;
        String responseString = null;
        try {
            // Try connection
            HttpGet get = new HttpGet(params[0].path);
            get.addHeader("Authorization",
                    "Basic "
                            + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password)
                                    .getBytes()));
        response = httpclient.execute(get);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
        } else {
            // Closes the connection.
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (ClientProtocolException e) {
        Log.e(TAG, "ClientProtocolException");
        this.e = e;
    } catch (IOException e) {
        Log.e(TAG, "IOException");
        this.e = e;
    }
    return responseString;

当我尝试使用 https 时,我收到 No peer certificate 错误。所以我尝试使用这段代码: HttpClient httpclient = new DefaultHttpClient(httpParameters);

private HttpClient createHttpClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
            HttpProtocolParams.setUseExpectContinue(params, true);

            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            schReg.register(new Scheme("https", sf, 8080));
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);

            return new DefaultHttpClient(conMgr, params);

        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }

但这给了我一个Connection closed by peer 错误。

我做错了什么?我可以放心地忽略证书,因为它是一个带有自签名证书的内部网络,但是我无法控制 vert 并且我的应用程序的用户可能拥有不同的证书,所以我真的需要自动接受或绕过它。

谢谢

编辑 ------------------

在尝试以下 My-Name-Is 答案后: 我按照建议创建了一个 CustomX509TrustManager 类,然后像这样使用它创建一个自定义 HttpClient:

private HttpClient sslClient(HttpClient client) {
        try {
            CustomX509TrustManager tm = new CustomX509TrustManager();
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new MySSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = client.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", ssf, 8080));
            return new DefaultHttpClient(ccm, client.getParams());
        } catch (Exception ex) {
            return null;
        }
    }

最后像这样使用这个HttpClient:

private class httpGETTask extends AsyncTask<GetParams, Void, String> {
private Exception e = null;

@Override
protected String doInBackground(GetParams... params) {
    // Set connection parameters
    HttpParams httpParameters = new BasicHttpParams();
    int timeoutConnection = 15000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    int timeoutSocket = 15000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    Log.v(TAG, params[0].path);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    httpclient = sslClient(httpclient);

    HttpResponse response;
    String responseString = null;
    try {
        // Try connection
        HttpGet get = new HttpGet(params[0].path);
        get.addHeader("Authorization",
                "Basic "
                        + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password)
                                .getBytes()));

        response = httpclient.execute(get);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
        } else {
            // Closes the connection.
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (ClientProtocolException e) {
        Log.e(TAG, "ClientProtocolException");
        this.e = e;
    } catch (IOException e) {
        Log.e(TAG, "IOException");
        this.e = e;
    }
    return responseString;

记录的路径格式为https://ipaddress:8080/Page.html 但我得到一个Connection closed By Peer 错误:

05-24 08:20:32.500: E/ConnectionHelper(1129): IOException 05-24 08:20:32.550:E/ConnectionHelper(1129):异常加载内容 05-24 08:20:32.550: E/ConnectionHelper(1129): javax.net.ssl.SSLException:连接被对等方关闭 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native 方法) 05-24 08:20:32.550: E/ConnectionHelper(1129): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.(OpenSSLSocketImpl.java:643) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:614) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.io.SocketInputBuffer.(SocketInputBuffer.java:70) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:172) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 05-24 08:20:32.550:E/ConnectionHelper(1129):在 com.d_apps.my_app.connection_helpers.ConnectionHelper$httpGETTask.doInBackground(ConnectionHelper.java:114)

【问题讨论】:

    标签: java android ssl https httpclient


    【解决方案1】:

    如果您使用的是“不可信”(开发者)证书,那么下面是解决方案。我们需要信任所有证书,下面是这样做的方法。对于受信任的证书,它无需添加以下功能即可使用,我们只需将 http 更改为 https 即可。

    这是不信任证书的解决方案。

    在 HttpClient 方式中,您应该从 org.apache.http.conn.ssl.SSLSocketFactory 创建一个自定义类,而不是一个 org.apache.http.conn.ssl.SSLSocketFactory 本身

    例子就像...

    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.conn.ssl.SSLSocketFactory;
    public class MySSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");
    
        public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
            super(truststore);
    
            TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
    
            sslContext.init(null, new TrustManager[] { tm }, null);
        }
    
        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }
    
        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }
    

    并在创建 HttpClient 实例时使用此类。

    public HttpClient getNewHttpClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
    
            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
    
            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));
    
            ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    
            return new DefaultHttpClient(ccm, params);
        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }
    

    【讨论】:

    • @IgorGanapolsky 你解决了这个异常吗?我也一样。
    【解决方案2】:

    以下来源应该可以解决您的问题。

    import android.app.Activity;
    import android.widget.EditText;
    import android.os.Bundle;
    import org.apache.http.HttpResponse;
    import org.apache.http.Header
    import java.io.InputStream;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import android.util.Log;
    import android.view.Menu;
    public class MainActivity extends Activity {
    
        private EditText text;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            text = (EditText) findViewById(R.id.editText1);
            connect();
        }
    
        private void connect(){
            try {
                DataLoader dl = new DataLoader();
                String url = "https://IpAddress";
                HttpResponse response = dl.secureLoadData(url); 
    
                StringBuilder sb = new StringBuilder();
                sb.append("HEADERS:\n\n");
    
                Header[] headers = response.getAllHeaders();
                for (int i = 0; i < headers.length; i++) {
                    Header h = headers[i];
                    sb.append(h.getName()).append(":\t").append(h.getValue()).append("\n");
                }
    
                InputStream is = response.getEntity().getContent();
                StringBuilder out = new StringBuilder();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                for (String line = br.readLine(); line != null; line = br.readLine())
                    out.append(line);
                br.close();
    
                sb.append("\n\nCONTENT:\n\n").append(out.toString()); 
    
                Log.i("response", sb.toString());
                text.setText(sb.toString());
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }
    
    }
    
    
    import android.app.Application;
    import android.content.Context;
    import java.io.InputStream;
    public class MeaApplication extends Application {
    
        private static Context context;
    
        @Override
        public void onCreate() {
            super.onCreate();
            MeaApplication.context = getApplicationContext();
        }
    
        public static Context getAppContext() {
            return MeaApplication.context;
        }
    
        public static InputStream loadCertAsInputStream() {
            return MeaApplication.context.getResources().openRawResource(
                    R.raw.meacert);
        }
    
    }
    
    
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import javax.net.ssl.SSLContext;
    import java.security.KeyStore;
    import java.security.NoSuchAlgorithmException;
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.UnrecoverableKeyException;
    import javax.net.ssl.TrustManager;
    import java.net.Socket;
    import java.io.IOException;
    import java.net.UnknownHostException;
    /**
     * Taken from: http://janis.peisenieks.lv/en/76/english-making-an-ssl-connection-via-android/
     *
     */
    public class CustomSSLSocketFactory extends SSLSocketFactory {
        SSLContext sslContext = SSLContext.getInstance("TLS");
    
        public CustomSSLSocketFactory(KeyStore truststore)
                throws NoSuchAlgorithmException, KeyManagementException,
                KeyStoreException, UnrecoverableKeyException {
            super(truststore);
    
            TrustManager tm = new CustomX509TrustManager();
    
            sslContext.init(null, new TrustManager[] { tm }, null);
        }
    
        public CustomSSLSocketFactory(SSLContext context)
                throws KeyManagementException, NoSuchAlgorithmException,
                KeyStoreException, UnrecoverableKeyException {
            super(null);
            sslContext = context;
        }
    
        @Override
        public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port,
                    autoClose);
        }
    
        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }
    
    
    import javax.net.ssl.X509TrustManager;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.cert.CertificateFactory;
    public class CustomX509TrustManager implements X509TrustManager {
    
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
    
        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] certs,
                String authType) throws CertificateException {
    
            // Here you can verify the servers certificate. (e.g. against one which is stored on mobile device)
    
            // InputStream inStream = null;
            // try {
            // inStream = MeaApplication.loadCertAsInputStream();
            // CertificateFactory cf = CertificateFactory.getInstance("X.509");
            // X509Certificate ca = (X509Certificate)
            // cf.generateCertificate(inStream);
            // inStream.close();
            //
            // for (X509Certificate cert : certs) {
            // // Verifing by public key
            // cert.verify(ca.getPublicKey());
            // }
            // } catch (Exception e) {
            // throw new IllegalArgumentException("Untrusted Certificate!");
            // } finally {
            // try {
            // inStream.close();
            // } catch (IOException e) {
            // e.printStackTrace();
            // }
            // }
        }
    
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    
    }
    
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import java.io.IOException;
    import java.security.NoSuchAlgorithmException;
    import java.security.KeyManagementException;
    import java.net.URISyntaxException;
    import java.security.KeyStoreException;
    import java.security.UnrecoverableKeyException;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import java.security.SecureRandom;
    import org.apache.http.client.HttpClient;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.client.methods.HttpGet;
    public class DataLoader {
    
        public HttpResponse secureLoadData(String url)
                throws ClientProtocolException, IOException,
                NoSuchAlgorithmException, KeyManagementException,
                URISyntaxException, KeyStoreException, UnrecoverableKeyException {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { new CustomX509TrustManager() },
                    new SecureRandom());
    
            HttpClient client = new DefaultHttpClient();
    
            SSLSocketFactory ssf = new CustomSSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = client.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", ssf, 443));
            DefaultHttpClient sslClient = new DefaultHttpClient(ccm,
                    client.getParams());
    
            HttpGet get = new HttpGet(new URI(url));
            HttpResponse response = sslClient.execute(get);
    
            return response;
        }
    
    }
    

    【讨论】:

    • @benoffi7 当然。目前我手头没有源代码。不过,我今晚会添加导入。
    • @benoffi7 添加导入完成 :) 我没有再次编译项目,因为前段时间我从更高级的项目中提取了主要部分。不幸的是我找不到这个修改过的项目,所以如果缺少任何导入,请告诉我。
    • 在花了一天多的时间尝试一切之后,这段代码终于为我工作了。我所做的唯一更改是稍微修改它以与我的 POST 一起使用,因为我没有将 GET 用于 SSL。我的另一个区别是我没有扩展应用程序的类,并且我没有在本地加载任何证书。但是,它仍然可以正常工作。我想知道没有在本地加载我的证书,我是否会对任何漏洞敞开心扉,或者我仍然很好?或者我基本上是在不知情的情况下绕过身份验证?我不是 SSL 方面的专家,但它似乎运行顺利,没有任何错误。
    • 明白。感谢您的澄清。如果我的应用程序会出名(LifeLog24),我也会考虑添加这个额外的检查:)
    • @John 此解决方案不使用备用KeyStore,但您可以调整您的SSLSocketFactory 以支持此功能。上面的解决方案使用自定义的X509TrustManager,它根据证书的公钥决定是否允许应用程序访问特定的服务器。控制此行为的 checkServerTrusted 的自定义实现已被注释掉,因为它可能对其他环境没有用处。
    【解决方案3】:

    检查您设备的日期。您可能已将其更改为不同的年份。当孩子们使用我的手机时,我经常遇到这个问题。

    【讨论】:

    • +1 这似乎是您收到错误Νο peer certificate 时最常见的情况。
    【解决方案4】:

    在搜索此例外时,您得到的只是实施“允许所有证书”的建议。

    SSLPeerUnverifiedException 的 javadoc 指出:

    当对等方无法识别自己时(例如,没有证书、正在使用的特定密码套件不支持身份验证,或者在 SSL 握手期间没有建立对等方身份验证),将引发此异常。

    所以错误可能是连接非常不稳定/不稳定,并且请求需要花费大量时间。在我们的移动应用程序中,我们有时会遇到大量的连接/套接字超时以及这些 SSLPeerUnverifiedException。一些请求通过但需要 60 多秒 - 在这些情况下,网络连接简直糟透了。

    在这种情况下,不建议使用“允许所有证书”简单地强制执行此操作 - 而是实施适当的重试策略。

    【讨论】:

    • 套接字超时与SSLPeerUnverifiedException 无关。你得到一个,或者你得到另一个。
    • 我并不是说你可以同时得到两者。我不打算验证这一点,但当时我的经验是,在处理非常不稳定的连接时,当 SSL 握手期间的 Peer-Auth 被中断时,您可能会收到 SSLPeerUnverifiedException。在这种情况下,您当然应该以SSLHandshakeException 结束,但我不能 100% 确定您永远不会看到 SSLPeerUnverifiedException “误报”。你是@user207421 吗?
    【解决方案5】:

    如果您可以使用受信任的证书访问服务器,更好的解决方案是正确配置 SSL,因为在 SSL 验证方面,Android 比 iOS 和桌面浏览器更受限制

    此解决方案不需要对您的 android 应用进行任何更改,因此更干净。

    这是 apache 的 SSL 配置示例(将其添加到您的 VirtualHost 定义中,例如 /etc/apache2/sites-enabled)

    SSLEngine on
    SSLCertificateFile    YOUR_CERT_PATH
    SSLCACertificateFile  CA_ROOT_CERT_PATH
    SSLCertificateKeyFile KEY_PATH
    

    我遇到了同样的错误,当我添加 CA 根证书时,错误消失了,android 不再抱怨了。为这些文件提供正确的路径,重新启动 Apache 并再次测试。

    CA 根证书的文件可以包含根证书和中间证书

    您可以使用this site 测试您的 SSL 配置,并确保在 Certification Paths 下的结果中服务器正在发送所有必需的证书。

    【讨论】:

      【解决方案6】:

      允许 Android 的安全提供程序在启动您的应用时进行更新。

      5.0+ 之前的默认 Provider 不会禁用 SSLv3。如果您可以访问 Google Play 服务,那么从您的应用中修补 Android 的安全提供程序相对简单。

        private void updateAndroidSecurityProvider(Activity callingActivity) {
          try {
              ProviderInstaller.installIfNeeded(this);
          } catch (GooglePlayServicesRepairableException e) {
            // Thrown when Google Play Services is not installed, up-to-date, or  enabled
              // Show dialog to allow users to install, update, or otherwise    enable Google Play services.
             GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0);
          } catch (GooglePlayServicesNotAvailableException e) {
              Log.e("SecurityException", "Google Play Services not available.");
          }
      }
      

      来源: Patching the Security Provider with ProviderInstaller Provider

      【讨论】:

      • installIfNeeded(this) 是什么意思? 这个是什么?
      • @nani 干得好。感谢您与社区分享此内容。我不太可能及时发现这一点。
      【解决方案7】:

      我最初使用的是HttpsURLConnection,但它无法始终如一地工作,所以我决定使用HttpClient。现在可以了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-20
        • 2012-02-07
        • 1970-01-01
        • 2018-05-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多