天天看點

http 和 https請求,證書生成X509證書信任管理器類

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class MyX509TrustManager implements X509TrustManager {

	@Override
	public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
		// TODO Auto-generated method stub
		// 檢查用戶端證書
	}

	@Override
	public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
		// TODO Auto-generated method stub
		// 檢查伺服器端證書  
	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		// TODO Auto-generated method stub
		// 傳回受信任的X509證書數組 
		return null;
	}

}
           

X509證書信任管理器類

public static String  httpPostUtil(String pathUrl, JSONObject content) {
		boolean isHttps = true;
		String strResult = "";
		DataOutputStream out = null;
		BufferedReader reader = null;
		
		if(pathUrl.toLowerCase().startsWith("https:")){
			isHttps = true;
		}else{
			isHttps = false;
		}
		
		if(isHttps){
			SSLContext ctx = null;
	        try {
	            ctx = SSLContext.getInstance("TLS");
	            ctx.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() }, new SecureRandom());
	        } catch (KeyManagementException e) {
	            e.printStackTrace();
	        } catch (NoSuchAlgorithmException e) {
	            e.printStackTrace();
	        }
	        SSLSocketFactory ssf = ctx.getSocketFactory();
	        HttpsURLConnection httpsConn = null;
	        try{
		        URL url = new URL(pathUrl);
		        httpsConn = (HttpsURLConnection) url.openConnection();
		        httpsConn.setSSLSocketFactory(ssf);
		        httpsConn.setHostnameVerifier(new HostnameVerifier() {
		            @Override
		            public boolean verify(String arg0, SSLSession arg1) {
		                return true;
		            }
		        });
		        httpsConn.setRequestMethod("POST");
		        httpsConn.setDoInput(true);
		        httpsConn.setDoOutput(true);
		        httpsConn.setConnectTimeout(6000);
		        httpsConn.setReadTimeout(6000);
		        
		        httpsConn.setRequestProperty("Connection", "keep-alive");  //設定連接配接的狀态
		        httpsConn.setRequestProperty("Transfer-Encoding", "chunked");//設定傳輸編碼
		        httpsConn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
		        
		        out = new DataOutputStream(httpsConn.getOutputStream());
		        out.write(content.toString().getBytes("UTF-8"));
		        
		        out.flush();
				
		        out.close();
		        StringBuffer stringbuffer = new StringBuffer();
		        if (httpsConn.getResponseCode()==200){
		        	reader = new BufferedReader(new InputStreamReader(httpsConn.getInputStream()));
		        	String line="";
		        	while ((line = reader.readLine()) != null) {
		        		stringbuffer.append(line);
					}
		        	strResult = stringbuffer.toString();
		        	reader.close();
		        }else{

		        }
		        httpsConn.disconnect();
		        
		        
	        }catch (Exception e) {
				// TODO: handle exception
	        	if(httpsConn!=null){
	        		httpsConn.disconnect();
	        	}
			}
		}else{
			URL postUrl = null;
			HttpURLConnection connection = null;
			try {
				postUrl = new URL(pathUrl);
				connection = (HttpURLConnection) postUrl.openConnection();
				
				connection.setDoOutput(true);// http正文内,是以需要設為true, 預設情況下是false;
	            connection.setDoInput(true);
	            connection.setConnectTimeout(6000);
	            connection.setReadTimeout(6000);
				
				connection.setRequestMethod("POST");

		        connection.setRequestProperty("Connection", "keep-alive"); 
		        connection.setRequestProperty("Transfer-Encoding", "chunked");
		        connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");

		        out = new DataOutputStream(connection.getOutputStream());
		        out.write(content.toString().getBytes("UTF-8"));
		        
		        out.flush();
				
		        out.close();
		        StringBuffer stringbuffer = new StringBuffer();
		        if (connection.getResponseCode()==200){
		        	reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		        	String line="";
		        	while ((line = reader.readLine()) != null) {
		        		stringbuffer.append(line);
					}
		        	strResult = stringbuffer.toString();
		        	reader.close();
		        }else{

		        }
		        connection.disconnect();
			} catch (MalformedURLException e4) {
				// TODO Auto-generated catch block
				e4.printStackTrace();
				if(connection!=null){
					connection.disconnect();
	        	}
			}catch (IOException e3) {
				e3.printStackTrace();
				if(connection!=null){
					connection.disconnect();
	        	}
			}
		}
		
		logger.info("strResult="+strResult);
    	return strResult;
	}
           

生成證書

1:什麼是HTTPS?

HTTPS其實是有兩部分組成:HTTP + SSL / TLS,

也就是在HTTP上又加了一層處理加密資訊的子產品,并且會進行身份的驗證。

問題:

Firebug和postman之類的浏覽器調試工具,為什麼擷取到的是明文?

解答:

SSL是對傳輸的資料進行加密,針對的是傳輸過程的安全。 

firebug之類的浏覽器調試工具,

因為他們得到的是用戶端加密之前/解密之後的資料,是以是明文的。

2:什麼是自簽名證書?

就是自己生成的證書,并不是官方生成的證書。

除非是很正式的項目,否則使用自己簽發的證書即可,因為官方生成證書是要花錢滴。

使用JDK自帶工具KeyTool 生成自簽發證書!

第一步:為伺服器生成證書

需要使用jdk自帶的keytool來生成證書,如果已配置java環境變量,在任何目錄啟動指令行輸入以下指令即可,若未配置java環境變量,則需要到jdk安裝目錄bin檔案夾下啟動指令行;

使用keytool指令生成證書:

keytool 

-genkey 

-alias tomcat(别名) 

-keypass 123456(别名密碼) 

-keyalg RSA(算法) 

-keysize 1024(密鑰長度) 

-validity 365(有效期,天機關) 

-keystore c:/tomcat.keystore(指定生成證書的位置和證書名稱) 

-storepass 123456(擷取keystore資訊的密碼)

C:\Program Files\Java\jdk1.7.0_75\bin>keytool -genkey -alias appsys -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore c:/cer/appsys.keystore -storepass 123456

您的名字與姓氏是什麼?

  [Unknown]:  test

您的組織機關名稱是什麼?

  [Unknown]:  test

您的組織名稱是什麼?

  [Unknown]:  test

您所在的城市或區域名稱是什麼?

  [Unknown]:  sz

您所在的省/市/自治區名稱是什麼?

  [Unknown]:  gd

該機關的雙字母國家/地區代碼是什麼?

  [Unknown]:  china

CN=webcm, OU=webcm, O=webcm, L=sz, ST=gd, C=china是否正确?

  [否]:  y

第二步:為用戶端生成證書

為浏覽器生成證書,以便讓伺服器來驗證它。

為了能将證書順利導入至IE和Firefox,證書格式應該是PKCS12,

是以,使用如下指令生成:

keytool 

-genkey 

-alias client 

-keypass 123456

-keyalg RSA 

-storetype PKCS12 

-keypass 123456 

-storepass 123456 

-keystore c:/client.p12

C:\Program Files\Java\jdk1.7.0_75\bin>keytool -genkey -alias appclient -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -storetype PKCS12 -keystore c:/cer/appclient.p12 -storepass 123456

您的名字與姓氏是什麼?

  [Unknown]:  test

您的組織機關名稱是什麼?

  [Unknown]:  test

您的組織名稱是什麼?

  [Unknown]:  test

您所在的城市或區域名稱是什麼?

  [Unknown]:  sz

您所在的省/市/自治區名稱是什麼?

  [Unknown]:  gd

該機關的雙字母國家/地區代碼是什麼?

  [Unknown]:  china

CN=webcm, OU=webcm, O=webcm, L=sz, ST=gd, C=china是否正确?

  [否]:  y

第三步:讓伺服器信任用戶端證書

1、

由于不能直接将PKCS12格式的證書庫導入,

必須先把用戶端證書導出為一個單獨的CER檔案,使用如下指令:

keytool -export -alias appclient -keystore c:/cer/appclient.p12 -storetype PKCS12 -keypass 123456 -file c:/cer/appclient.cer

注意:

Keypass:指定CER檔案的密碼,但會被忽略,而要求重新輸入

2、

将該檔案導入到伺服器的證書庫,添加為一個信任證書:

keytool -import -v -file c:/cer/appclient.cer -keystore c:/cer/appsys.keystore -storepass 123456

完成之後通過list指令檢視伺服器的證書庫,

可以看到兩個證書,一個是伺服器證書,一個是受信任的用戶端證書:

keytool -list -v -keystore c:/cer/appsys.keystore

第四步:讓用戶端信任伺服器證書

1、

由于是雙向SSL認證,用戶端也要驗證伺服器證書,

是以,必須把伺服器證書添加到浏覽器的“受信任的根證書頒發機構”。

由于不能直接将keystore格式的證書庫導入,

必須先把伺服器證書導出為一個單獨的CER檔案,使用如下指令:

keytool -keystore c:/cer/appsys.keystore -export -alias appsys -file c:/cer/appserver.cer

2、

輕按兩下appserver.cer檔案,按照提示安裝證書,

将證書填入到“受信任的根證書頒發機構”。

填入方法:

打開浏覽器   - 工具  -  internet選項-内容- 證書-把中級證書頒發機構裡的www.localhost.com(該名稱即時你前面生成證書時填寫的名字與姓氏)證書導出來-再把導出來的證書導入  受信任的根頒發機構  就OK了。

步驟五:配置Tomcat伺服器

<Connector port="8081" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true"

     scheme="https" secure="true" clientAuth="false" sslProtocol="TLS"

    keystoreFile="/home/apache-tomcat/te.keystore" keystorePass="123456"

    truststoreFile="/home/apache-tomcat/te.keystore"

    truststorePass="123456" connectionTimeout="20000"

        redirectPort="8443" useBodyEncodingForURI="true" URIEncoding="UTF-8" />

屬性說明:

clientAuth:設定是否雙向驗證,預設為false,設定為true代表雙向驗證

keystoreFile:伺服器證書檔案路徑

keystorePass:伺服器證書密碼

truststoreFile:用來驗證用戶端證書的根證書,此例中就是伺服器證書

truststorePass:根證書密碼

注意:

① 設定clientAuth屬性為True時,需要手動導入用戶端證書才能通路。

② 要通路https請求 需要通路8443端口,通路http請求則通路Tomcat預設端口(你自己設定的端口,預設8080)即可。
           

 同時也支援http需要再加上下面配置:

<Connector

        port="8082"

        protocol="HTTP/1.1"

        connectionTimeout="20000"

        redirectPort="8443" useBodyEncodingForURI="true" URIEncoding="UTF-8" />

然後重新開機tomcat,使用http,https通路成功。

小知識:

強制 https 通路

在 tomcat /conf/web.xml 中的 </welcome- file-list> 後面加上這

<login-config>    
<!-- Authorization setting for SSL -->    
<auth-method>CLIENT-CERT</auth-method>    
<realm-name>Client Cert Users-only Area</realm-name>    
</login-config>    
<security-constraint>    
<!-- Authorization setting for SSL -->    
<web-resource-collection >    
<web-resource-name >SSL</web-resource-name>    
<url-pattern>/*</url-pattern>    
</web-resource-collection>    
<user-data-constraint>    
<transport-guarantee>CONFIDENTIAL</transport-guarantee>    
</user-data-constraint>    
</security-constraint> 

完成以上步驟後,在浏覽器中輸入http的通路位址也會自動轉換為https
           

如不能通路,先檢視端口是否被禁用了。

注:浏覽器不能同時通路HTTP,HTTPS,需要關閉浏覽器後再通路另位址。