Android使用https連結
阿新 • • 發佈:2019-01-23
Https與Http類似,只不過Https一般是通過post請求伺服器,但是Https與http不同的是Https與伺服器會話是處於連線狀態。http則傳送請求後連線就會斷開。
另外使用HttpsURLConnection時需要實現HostnameVerifier 和 X509TrustManager,這兩個實現是必須的,要不會報安全驗證異常。
package cn.yws.httpstest; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.math.BigInteger; import java.net.URL; import java.security.Principal; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.CoreConnectionPNames; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; public class MainActivity extends Activity { private static final String tag = MainActivity.class.getSimpleName(); private EditText editText1; private Handler handler=new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 10: { String html=(String) msg.obj; //子執行緒不能直接操作editText1 editText1.setText(html); } break; default: break; } return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View button = this.findViewById(R.id.button); editText1=(EditText) findViewById(R.id.editText1); button.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { onclick(); }}); } //方法一使用HttpsURLConnection public void GetHttpsPost(String urlPath) throws Exception { URL url = new URL(urlPath); SSLContext sslctxt = SSLContext.getInstance("TLS"); sslctxt.init(null, new TrustManager[]{new MyX509TrustManager()}, new java.security.SecureRandom()); HttpsURLConnection conn = (HttpsURLConnection)url.openConnection(); //多了兩個 conn.setSSLSocketFactory(sslctxt.getSocketFactory()); conn.setHostnameVerifier(new MyHostnameVerifier()); conn.connect(); int respCode = conn.getResponseCode(); Log.d(tag, "ResponseCode="+respCode); InputStream input = conn.getInputStream(); String result = toString(input); //Log.d(tag, "result:"+result); Message msg=Message.obtain(); msg.what=10; msg.obj=result; handler.sendMessage(msg); //子執行緒不能直接操作editText1 //editText1.setText(result); input.close(); conn.disconnect(); } private String toString(InputStream input){ String content = null; try{ InputStreamReader ir = new InputStreamReader(input); BufferedReader br = new BufferedReader(ir); StringBuilder sbuff = new StringBuilder(); while(null != br){ String temp = br.readLine(); if(null == temp)break; sbuff.append(temp).append(System.getProperty("line.separator")); } content = sbuff.toString(); }catch(Exception e){ e.printStackTrace(); } return content; } public void runHttpsClient(View view) { String path="https://login.taobao.com/member/login.jhtml?spm=1.6659421.754894437.1.2pSgMy&f=top&redirectURL=http%3A%2F%2Fwww.taobao.com%2F"; String html; try { html = sendHttpsClientPOSTRequest(path, null, "GBK"); Message msg=Message.obtain(); msg.what=10; msg.obj=html; handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } public static String sendHttpsClientPOSTRequest(String path, Map<String, String> params, String encoding) throws Exception{ List<NameValuePair> pairs = new ArrayList<NameValuePair>();//存放請求引數 if(params!=null && !params.isEmpty()){ for(Map.Entry<String, String> entry : params.entrySet()){ pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } } UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs, encoding); HttpPost httpPost = new HttpPost(path); httpPost.setEntity(entity); HttpClient client = HttpClientHelper.getHttpClient(); client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5*1000); HttpResponse response = client.execute(httpPost); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { } return new String(readStream(response.getEntity().getContent()),encoding); } public static byte[] readStream(InputStream inStream) throws Exception { ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = -1; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); return outSteam.toByteArray(); } private void onclick(){ new Thread(new Runnable(){ @Override public void run() { try{ String str = "https://www.oschina.net/home/login?goto_page=http%3A%2F%2Fwww.oschina.net%2F"; //String str="https://login.taobao.com/member/login.jhtml?spm=1.6659421.754894437.1.2pSgMy&f=top&redirectURL=http%3A%2F%2Fwww.taobao.com%2F"; GetHttpsPost(str); }catch(Exception e){ e.printStackTrace(); } } }).start();; } //要實現x209證書認證 static class MyX509TrustManager implements X509TrustManager{ @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { if(null != chain){ for(int k=0; k < chain.length; k++){ X509Certificate cer = chain[k]; print(cer); } } Log.d(tag, "check client trusted. authType="+authType); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { if(null != chain){ for(int k=0; k < chain.length; k++){ X509Certificate cer = chain[k]; print(cer); } } Log.d(tag, "check servlet trusted. authType="+authType); //是否信任伺服器 Principal principal = null; boolean isOK=false; for(X509Certificate x509Certificate : chain){ principal = x509Certificate.getSubjectDN(); Log.d(tag, "principal.getName():"+principal.getName()); if(principal != null &&(principal.getName().indexOf("www.oschina.net")!=-1)){ isOK=true; break; //return ; } } if(isOK==false){ Log.d(tag, "訪問非法域名"); return ; } } @Override public X509Certificate[] getAcceptedIssuers() { Log.d(tag, "get acceptedissuer"); return null; } private void print(X509Certificate cer){ int version = cer.getVersion(); String sinname = cer.getSigAlgName(); String type = cer.getType(); String algorname = cer.getPublicKey().getAlgorithm(); BigInteger serialnum = cer.getSerialNumber(); Principal principal = cer.getIssuerDN(); String principalname = principal.getName(); Log.d(tag, "version="+version+", sinname="+sinname+", type="+type+", algorname="+algorname+", serialnum="+serialnum+", principalname="+principalname); } } //要實現主機名驗證 static class MyHostnameVerifier implements HostnameVerifier{ @Override public boolean verify(String hostname, SSLSession session) { Log.d(tag, "hostname="+hostname+",PeerHost= "+session.getPeerHost()); return true; } } }
package cn.yws.httpstest; 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 javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnManagerParams; import org.apache.http.conn.scheme.PlainSocketFactory; 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.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.protocol.HTTP; //方法二、使用HttpClient public class HttpClientHelper { private static HttpClient httpClient; private HttpClientHelper() { } public static synchronized HttpClient getHttpClient() { if (null == httpClient) { // 初始化工作 try { KeyStore trustStore = KeyStore.getInstance(KeyStore .getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new SSLSocketFactoryEx(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); // 設定連線管理器的超時 ConnManagerParams.setTimeout(params, 10000); // 設定連線超時 HttpConnectionParams.setConnectionTimeout(params, 10000); // 設定socket超時 HttpConnectionParams.setSoTimeout(params, 10000); // 設定http https支援 SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory .getSocketFactory(), 80)); schReg.register(new Scheme("https", sf, 443)); ClientConnectionManager conManager = new ThreadSafeClientConnManager( params, schReg); httpClient = new DefaultHttpClient(conManager, params); } catch (Exception e) { e.printStackTrace(); return new DefaultHttpClient(); } } return httpClient; } } class SSLSocketFactoryEx extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } }; 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(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.yws.httpstest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="4" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="cn.yws.httpstest.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/ll"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="50dip"
android:text="@string/hello_world" />
<Button
android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:onClick="runHttpsClient"
android:text="@string/httpsclient" />
</LinearLayout>
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignTop="@+id/ll"
android:layout_marginTop="150dip"
android:inputType="textMultiLine" >
<requestFocus />
</EditText>
</RelativeLayout>
另外附上tomcat配置https雙向認證文件。