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双向认证文档。
http://download.youkuaiyun.com/detail/earbao/7120093