简体   繁体   English

如何从Android应用程序中使用HTTPS休息服务

[英]How to consume HTTPS rest service from android application

I am very much new to android application development. 我是Android应用程序开发的新手。 I am working on a demo project, where I am trying to use my android application as a client of a WCF REST service created on C#.net. 我正在开发一个演示项目,我试图将我的android应用程序用作在C#.net上创建的WCF REST服务的客户端。 The service is already hosted in a internet server and is working fine as I am using the same service in my other .Net web applications (as client). 该服务已经托管在互联网服务器中,并且工作正常,因为我在其他.Net Web应用程序(作为客户端)中使用相同的服务。 But when I am trying to access the same REST service (returning a JSON object) from my android application it's throwing following exception. 但是,当我尝试从我的Android应用程序访问相同的REST服务(返回一个JSON对象)时,它抛出以下异常。

“java.io.IOException: SSL handshake failure: Failure in SSL library, usually a protocol error error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:585 0xaf586674:0x00000000)” “java.io.IOException:SSL握手失败:SSL库失败,通常是协议错误错误:140770FC:SSL例程:SSL23_GET_SERVER_HELLO:未知协议(外部/ openssl / ssl / s23_clnt.c:585 0xaf586674:0x00000000)”

Following is the code I used to connect the service. 以下是我用来连接服务的代码。

final String url = "https://mywebsite.com/service/myservice.svc/userid/" + usrid + "/" + password + "/authenticate";

        Uri uri = Uri.parse(url);
        HttpClient httpclient = new DefaultHttpClient();
        HttpHost host = new HttpHost(uri.getHost(), 443, uri.getScheme());
        HttpPost httppost = new HttpPost(uri.getPath());
        try {
            HttpResponse response = httpclient.execute(host, httppost);  // Throwing exception on this line
               HttpEntity entity = response.getEntity();
            if (entity != null) { 
                InputStream instream = entity.getContent();
                String result= convertStreamToString(instream);
                JSONArray nameArray=json.names();
                JSONArray valArray=json.toJSONArray(nameArray);
                for(int i=0;i<valArray.length();i++)
                {
                    nameArray.getString(i);
                } 
                instream.close();
            }


        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

Should I need to create a SSLContext with my own TrustManager in order to ignore the SSL certificate error please confirm. 我是否需要使用自己的TrustManager创建SSLContext以忽略SSL证书错误,请确认。 If yes, could you please provide the code example as well. 如果是,请您提供代码示例。

The code that you have mentioned will work in a real device. 您提到的代码将在真实设备中使用。 The problem that you presented is caused by the firewall in your PC that blocks the 443 port. 您提出的问题是由PC中阻止443端口的防火墙引起的。

Try to disable your firewall and try your application in the emulator. 尝试禁用防火墙并在模拟器中尝试应用程序。 I believe it will work. 我相信它会奏效。

Yes.. You need to create a SSLContext with your own TrustManager in order to ignore the SSL certificate error. 是..您需要使用自己的TrustManager创建SSLContext,以忽略SSL证书错误。

EasySSLSocketFactory.java EasySSLSocketFactory.java

 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;

 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;

 import org.apache.http.conn.ConnectTimeoutException;
 import org.apache.http.conn.scheme.LayeredSocketFactory;
 import org.apache.http.conn.scheme.SocketFactory;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;

public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory {

private SSLContext sslcontext = null;

private static SSLContext createEasySSLContext() throws IOException {
    try {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
        return context;
    } catch (Exception e) {
        throw new IOException(e.getMessage());
    }
}

private SSLContext getSSLContext() throws IOException {
    if (this.sslcontext == null) {
        this.sslcontext = createEasySSLContext();
    }
    return this.sslcontext;
}

/**
 * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int,
 *      java.net.InetAddress, int, org.apache.http.params.HttpParams)
 */
public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort,
        HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
    int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
    int soTimeout = HttpConnectionParams.getSoTimeout(params);
    InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
    SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());

    if ((localAddress != null) || (localPort > 0)) {
        // we need to bind explicitly
        if (localPort < 0) {
            localPort = 0; // indicates "any"
        }
        InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
        sslsock.bind(isa);
    }

    sslsock.connect(remoteAddress, connTimeout);
    sslsock.setSoTimeout(soTimeout);
    return sslsock;

}

/**
 * @see org.apache.http.conn.scheme.SocketFactory#createSocket()
 */
public Socket createSocket() throws IOException {
    return getSSLContext().getSocketFactory().createSocket();
}

/**
 * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
 */
public boolean isSecure(Socket socket) throws IllegalArgumentException {
    return true;
}

/**
 * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int,
 *      boolean)
 */
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
        UnknownHostException {
    return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}

// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------

public boolean equals(Object obj) {
    return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class));
}

public int hashCode() {
    return EasySSLSocketFactory.class.hashCode();
}

}

EasyX509TrustManager.java EasyX509TrustManager.java

import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class EasyX509TrustManager implements X509TrustManager {

private X509TrustManager standardTrustManager = null;

/**
 * Constructor for EasyX509TrustManager.
 */
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
    super();
    TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    factory.init(keystore);
    TrustManager[] trustmanagers = factory.getTrustManagers();
    if (trustmanagers.length == 0) {
        throw new NoSuchAlgorithmException("no trust manager found");
    }
    this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}

/**
 * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
 */
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
    standardTrustManager.checkClientTrusted(certificates, authType);
}

/**
 * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
 */
public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
    if ((certificates != null) && (certificates.length == 1)) {
        certificates[0].checkValidity();
    } else {
        standardTrustManager.checkServerTrusted(certificates, authType);
    }
}

/**
 * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
 */
public X509Certificate[] getAcceptedIssuers() {
    return this.standardTrustManager.getAcceptedIssuers();
}

}

Now Call Https Service: 现在拨打Https服务:

 String urlToSendRequest = "https://example.com";
            String targetDomain = "example.com";

    DefaultHttpClient httpClient = new DefaultHttpClient();

     SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http",    PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));

HttpParams params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
                params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
            params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
    HttpProtocolParams.setContentCharset(params, "utf8");
    ClientConnectionManager cm =  new ThreadSafeClientConnManager(params, schemeRegistry);
    httpClient = new DefaultHttpClient(cm, params);

    HttpHost targetHost = new HttpHost(targetDomain, 443, "https");
            // Using POST here
    HttpPost httpPost = new HttpPost(urlToSendRequest);
            // Make sure the server knows what kind of a response we will accept

    // Also be sure to tell the server what kind of content we are sending
    httpPost.addHeader("Content-Type", "application/xml"); 

    StringEntity entity = new StringEntity("<input>test</input>", "UTF-8");
            entity.setContentType("application/xml");
            httpPost.setEntity(entity);


CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            //set the user credentials for our site "example.com"
credentialsProvider.setCredentials(new AuthScope(targetDomain, AuthScope.ANY_PORT),
            new UsernamePasswordCredentials("", ""));
            HttpContext context = new BasicHttpContext();
context.setAttribute("http.auth.credentials-provider", credentialsProvider);

            // execute is a blocking call, it's best to call this code in a
            // thread separate from the ui's
HttpResponse response = httpClient.execute(httpPost, context);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM