Java Android上的HTTPS身份验证

Java Android上的HTTPS身份验证,java,android,https,authorization,Java,Android,Https,Authorization,我有一些Android的HTTP认证代码。但它不适用于https身份验证。如何在https授权下重新考虑代码 HTTP验证代码如下: HttpUriRequest request = new HttpGet(HOST); String credentials = login + ":" + mPassword; authString = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); Shared

我有一些Android的HTTP认证代码。但它不适用于https身份验证。如何在https授权下重新考虑代码

HTTP验证代码如下:

HttpUriRequest request = new HttpGet(HOST);
String credentials = login + ":" + mPassword;
authString = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("auth", authString);
editor.apply();
request.addHeader("Authorization", authString);
HttpClient httpClient = new DefaultHttpClient();

int result = 0;
try {
    HttpResponse response = httpClient.execute(request);
    result = response.getStatusLine().getStatusCode();
    System.out.println(response.getStatusLine());
} catch (Exception e) {
    result = -1;
}
return result;
然而,HttpClient的默认行为适用于大多数用途 您可能需要配置一些方面。最 自定义SSL的常见要求包括:

  • 能够接受自签名或不受信任的SSL证书。这是由带有消息Unrecognized SSL的SSLexException突出显示的 尝试连接时抛出的握手(或类似握手)
  • 您希望使用第三方SSL库,而不是Sun的默认实现
  • 您可能需要自定义协议的实现:

    Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
    Protocol.registerProtocol("https", 
    new Protocol("https", new MySSLSocketFactory(), 443));
    HttpClient httpclient = new HttpClient();
    GetMethod httpget = new GetMethod("https://www.whatever.com/");
    try {
      httpclient.executeMethod(httpget);
      System.out.println(httpget.getStatusLine());
    } finally {
      httpget.releaseConnection();
    }
    
    mysslssocketfactory
    是一个自定义套接字工厂,它实现了
    org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
    接口 您可以参考此链接:

    然而,HttpClient的默认行为适用于大多数用途 您可能需要配置一些方面。最 自定义SSL的常见要求包括:

  • 能够接受自签名或不受信任的SSL证书。这是由带有消息Unrecognized SSL的SSLexException突出显示的 尝试连接时抛出的握手(或类似握手)
  • 您希望使用第三方SSL库,而不是Sun的默认实现
  • 您可能需要自定义协议的实现:

    Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
    Protocol.registerProtocol("https", 
    new Protocol("https", new MySSLSocketFactory(), 443));
    HttpClient httpclient = new HttpClient();
    GetMethod httpget = new GetMethod("https://www.whatever.com/");
    try {
      httpclient.executeMethod(httpget);
      System.out.println(httpget.getStatusLine());
    } finally {
      httpget.releaseConnection();
    }
    
    mysslssocketfactory
    是一个自定义套接字工厂,它实现了
    org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
    接口
    您可以引用此链接:

    我使用自定义ssl套接字工厂并使用参数创建HTTP客户端解决了此问题

    CustomSSLSocketFactory:

    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 CustomSSLSocketFactory extends SSLSocketFactory{
          SSLContext sslContext = SSLContext.getInstance("TLS");
          /**
           * Generate Certificate for ssl connection
           * @param truststore
           * @throws NoSuchAlgorithmException
           * @throws KeyManagementException
           * @throws KeyStoreException
           * @throws UnrecoverableKeyException
           */
          public CustomSSLSocketFactory(KeyStore truststore)
                      throws NoSuchAlgorithmException, KeyManagementException,
                      KeyStoreException, UnrecoverableKeyException {
                super(truststore);
                TrustManager tm = new X509TrustManager(){
                      @Override
                      public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                                  throws CertificateException {
                      }
                      @Override
                      public void checkServerTrusted(X509Certificate[] chain,
                                  String authType) throws CertificateException {
                      }
                      @Override
                      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();
          }
    }
    
    用于创建HTTP客户端的End util:

    import java.security.KeyStore;
    import org.apache.http.client.HttpClient;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpParams;
    
    public class HTTPUtils {
          /**
           * HttpClient
           * @param isHTTPS
           * @return
           */
          public static HttpClient getNewHttpClient(boolean isHTTPS) {
                try {
                      if(!isHTTPS){
                            return getNewHttpClient();
                      }
                      KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                      trustStore.load(null, null);
                      SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
                      sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
                      HttpParams params = new BasicHttpParams();
                      SchemeRegistry registry = new SchemeRegistry();
                      registry.register(new Scheme("https", sf, 443));
    
                      ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
                      return new DefaultHttpClient(ccm, params);
                } catch (Exception e) {
                      return null;
                }
          }
          /**
           * HttpClient for http request
           * @return
           */
          private static HttpClient getNewHttpClient(){
                HttpParams params = new BasicHttpParams();
                return new DefaultHttpClient(params);
          }
    }
    
    例如:

    String credentials = login + ":" + mPassword;
                authString = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
                HttpClient httpclient = HTTPUtils.getNewHttpClient(HOST.startsWith(HTTPS_STRING));
                URI newURI = URI.create(HOST);
                HttpGet httpGet =  new HttpGet(newURI);
                httpGet.setHeader("Authorization", authString);
    
                try {
                    HttpResponse response = httpclient.execute(httpGet);
                    int code = response.getStatusLine().getStatusCode();
                    return code;
    ...
    

    我解决了这个问题,使用自定义ssl套接字工厂并使用params创建HTTP客户端

    CustomSSLSocketFactory:

    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 CustomSSLSocketFactory extends SSLSocketFactory{
          SSLContext sslContext = SSLContext.getInstance("TLS");
          /**
           * Generate Certificate for ssl connection
           * @param truststore
           * @throws NoSuchAlgorithmException
           * @throws KeyManagementException
           * @throws KeyStoreException
           * @throws UnrecoverableKeyException
           */
          public CustomSSLSocketFactory(KeyStore truststore)
                      throws NoSuchAlgorithmException, KeyManagementException,
                      KeyStoreException, UnrecoverableKeyException {
                super(truststore);
                TrustManager tm = new X509TrustManager(){
                      @Override
                      public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                                  throws CertificateException {
                      }
                      @Override
                      public void checkServerTrusted(X509Certificate[] chain,
                                  String authType) throws CertificateException {
                      }
                      @Override
                      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();
          }
    }
    
    用于创建HTTP客户端的End util:

    import java.security.KeyStore;
    import org.apache.http.client.HttpClient;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpParams;
    
    public class HTTPUtils {
          /**
           * HttpClient
           * @param isHTTPS
           * @return
           */
          public static HttpClient getNewHttpClient(boolean isHTTPS) {
                try {
                      if(!isHTTPS){
                            return getNewHttpClient();
                      }
                      KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                      trustStore.load(null, null);
                      SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
                      sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
                      HttpParams params = new BasicHttpParams();
                      SchemeRegistry registry = new SchemeRegistry();
                      registry.register(new Scheme("https", sf, 443));
    
                      ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
                      return new DefaultHttpClient(ccm, params);
                } catch (Exception e) {
                      return null;
                }
          }
          /**
           * HttpClient for http request
           * @return
           */
          private static HttpClient getNewHttpClient(){
                HttpParams params = new BasicHttpParams();
                return new DefaultHttpClient(params);
          }
    }
    
    例如:

    String credentials = login + ":" + mPassword;
                authString = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
                HttpClient httpclient = HTTPUtils.getNewHttpClient(HOST.startsWith(HTTPS_STRING));
                URI newURI = URI.create(HOST);
                HttpGet httpGet =  new HttpGet(newURI);
                httpGet.setHeader("Authorization", authString);
    
                try {
                    HttpResponse response = httpclient.execute(httpGet);
                    int code = response.getStatusLine().getStatusCode();
                    return code;
    ...
    

    “不起作用”永远都不是一个足够好的错误描述。请扩展它,例如使用错误消息或堆栈跟踪。它在以下行冻结:HttpResponse response=httpClient.execute(request);“不起作用”永远都不是一个足够好的错误描述。请扩展它,例如使用错误消息或堆栈跟踪。它在以下行冻结:HttpResponse response=httpClient.execute(request);什么是我的袜子工厂?@OkadzakiTomoe。。请检查,我已经更新了答案,我不明白你的答案。什么是协议对象?@OkadzakiTomoe抱歉,您可能需要将apache http网络库添加到您的项目中。@OkadzakiTomoe。。您作为答案发布的链接实际上是在ANDROID上下文中执行建议的操作(创建自定义ssl套接字)。不管怎样,很高兴你解决了。我的袜子工厂是什么?@OkadzakiTomoe。。请检查,我已经更新了答案,我不明白你的答案。什么是协议对象?@OkadzakiTomoe抱歉,您可能需要将apache http网络库添加到您的项目中。@OkadzakiTomoe。。您作为答案发布的链接实际上是在ANDROID上下文中执行建议的操作(创建自定义ssl套接字)。无论如何,很高兴你解决了这个问题。不建议将链接作为答案发布,因为如果链接关闭/失效,这些答案将过时。我建议你以详细的形式补充你是如何解决的。因此,任何访问此页面的用户都只能获取此页面中的所有内容。另外,你也会因为写了好的答案而获得选票。不建议将链接作为答案发布,因为如果链接失效,这些答案就会过时。我建议你以详细的形式补充你是如何解决的。因此,任何访问此页面的用户都只能获取此页面中的所有内容。另外,你也会因为写了好的答案而获得选票。