Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android HTTPS和Cookies,API级别8_Java_Android_Session_Cookies_Https - Fatal编程技术网

Java Android HTTPS和Cookies,API级别8

Java Android HTTPS和Cookies,API级别8,java,android,session,cookies,https,Java,Android,Session,Cookies,Https,我正在编写一个Android应用程序,它必须通过HTTPS连接到服务器。我尝试的第一个解决方案是: (不要介意安全漏洞) 一切都很好(几乎),直到我意识到我还必须使用身份验证、会话和所有这些好东西。使用以下工具应该很好: CookieManager cookieManager = new CookieManager(); CookieHandler.setDefault(cookieManager); 但不幸的是,我们必须支持Android API级别8,这意味着上述两行代码将无法工作。有

我正在编写一个Android应用程序,它必须通过HTTPS连接到服务器。我尝试的第一个解决方案是: (不要介意安全漏洞)

一切都很好(几乎),直到我意识到我还必须使用身份验证、会话和所有这些好东西。使用以下工具应该很好:

CookieManager cookieManager = new CookieManager();  
CookieHandler.setDefault(cookieManager);
但不幸的是,我们必须支持Android API级别8,这意味着上述两行代码将无法工作。有鉴于此,我在互联网上搜寻了几个小时,试图使用Apache类构建一个解决方案,这些类似乎同时支持HTTPS和cookie

这是我设法拼凑起来的代码:

public class ConnectionMediator {
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) {
            }

            public void checkServerTrusted(X509Certificate[] chain, String authType) {
            }

            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();
    }
}
public void tryConnect(String url, String data) {
    try {
        //SSL Stuff
        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);

        DefaultHttpClient httpClient = new  DefaultHttpClient(ccm, params);

        //Cookie stuff
        HttpContext localContext = new BasicHttpContext();
        HttpResponse response = null;
        HttpPost httpPost = null;
        StringEntity tmp = null;

        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
        httpPost = new HttpPost(url);

        tmp = new StringEntity(data,"UTF-8");
        httpPost.setEntity(tmp);

        response = httpClient.execute(httpPost,localContext);
    } catch(Exception e) {
        Log.d("USR_DEBUG", e.getClass().toString() + ": " + e.getMessage());
    }

}
}
在撰写本文时,我得到了一个
NetworkOnMainThreadException
,但这并不重要;重要的是,我想指出的是,我不知道我在做什么,比如,简单地通过HTTPS连接并使用cookies,一个人必须使用13个我从未听说过的不同类。显然,我对HTTPS/JavaNet类的了解接近于零,但尽管如此,我还是希望有更直观的东西。因此,我的问题不是“这不起作用”类型的问题,而是“我应该做什么”,甚至是“我如何学习我必须做什么?”

多谢各位


一个非常困惑的程序员

我最初的问题有两个部分:第一,如何使用HTTPS,第二,如何同时使用cookies

我的问题不够透彻,因为我已经部分回答了它-我最初发布的代码与HTTPS有关,出现
NetworkOnMainThreadException
是因为我没有在单独的线程中运行代码,例如,使用
AsyncTask

但是,为了正确使用cookie,应使用类似于以下内容的解决方案:

public class State {
    private static HttpContext httpContext;
    public static HttpContext getHttpContext() {
        if(httpContext == null) {
            httpContext = new BasicHttpContext();
            CookieStore cookieStore = getCookieStore();
            httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        }
        return httpContext;
    }
    private static CookieStore cookieStore;
    public static CookieStore getCookieStore() {
        if(cookieStore == null) {
            cookieStore = new BasicCookieStore();
        }
        return cookieStore;
    }
}
我不确定这是否是“Android”的方式(使用静态类),但它可以工作:

    //...
    //Connection objects
    DefaultHttpClient httpClient = new DefaultHttpClient(ccm, params);
    HttpPost httpPost = null;

    //Cookie stuff
    HttpContext httpContext = State.getHttpContext();
    httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
    //....
如果使用相同的
CookieStore
HttpContext
,则每次使用另一个
HttpClient
似乎都会保留会话。
虽然这个答案可以让“一切正常”(这正是我现在需要的),但它并不是一个彻底的答案,因为它根本没有解释为什么需要10多个类来连接所有东西。

您所做的大部分工作只是因为您的https证书确实无法识别(很可能是自签名的?)。在我们的服务器决定做一个合适的证书之前,我坚持这样做。关于那些需要将所有内容连接在一起的10/13类,Apache HttpClient就是这样运行的:它的学习曲线有点陡峭,特别是如果您不知道HTTP/HTTPS规范的细节的话。您可以称之为过度工程化(例如,
NameValuePair
,真的吗?)或惊叹于它如何为HTTP中的每个概念提供一个类。无论哪种方式,你都有可能无法减少这个数字,正如HttpClient所描述的那样,这是使用“高度灵活且功能强大”的库所要付出的代价。它不仅仅是设计过度。这是一个地狱般的图书馆。使用它就像每次我输入一个角色时被一个巨大的仙人掌击中一样。您知道,当您需要使用8个不同的类来获取页面内容和状态时,有些东西是过度设计的。
    //...
    //Connection objects
    DefaultHttpClient httpClient = new DefaultHttpClient(ccm, params);
    HttpPost httpPost = null;

    //Cookie stuff
    HttpContext httpContext = State.getHttpContext();
    httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
    //....