[英]Using a self-signed certificate to create a secure client-server connection in android
我正在開發一個企業Android應用程序,因此有必要在我的測試階段在客戶端(android模擬器/測試手機)和服務器之間創建一個安全的連接,即使服務器的證書是自簽名的,而正在購買合法的證書由公司(我現在控制的東西)。
我需要信任服務器的自簽名證書及其證書授權,當然,它本身不受Android操作系統的信任。 我正在遵循谷歌關於在這個場景中幾乎逐字創建HTTPS環境的建議 。
我目前面臨的問題是我無法訪問我的.crt
文件,就像谷歌的例子一樣:
InputStream caInput = new BufferedInputStream(
new FileInputStream("load-der.crt"));
代替上述,我使用:
InputStream caInput = new BufferedInputStream(
getResources().openRawResource(R.raw.mycrtfile));
打開從mycrtfile.crt
派生的InputStream
,其中.crt
文件存在於/res/raw/mycrtfile.crt
。 但是,我在該行上得到NullPointerException
。
是否有更好的方法來存儲和訪問我需要作為InputStream
或FileInputStream
加載的cert文件,而不是存儲在res
目錄中的原始資源?
有不同的方法來解決您的問題,但這是我使用的方法:所有步驟都在這個鏈接http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/但有些部分可能會混淆所以我會解釋所有的過程:
1.將mycrtfile.crt存儲在知道路徑中我將說c:BKS / mycrtfile.crt。
2. - 要創建您的BKS或密鑰庫,您將需要文件bcprov-jdk15on-146.jar,這個類將為我們完成所有工作,有不同的版本,但這個適用於我http://www.bouncycastle .org / download / bcprov-jdk15on-146.jar還將此文件存儲到C:BKS /
3.-現在你將使用Keytool(keytool附帶Java SDK。你應該在包含javac的目錄中找到它)來生成我們的密鑰庫並確保它正常工作去你的cmd並輸入“Keytool”,你將看到可用的命令,或者您可以訪問“C:\\ Program Files(x86)\\ Java \\ jre7 \\ bin> keytool”。
4.-現在一切就緒,我們可以使用以下命令行生成密鑰庫:
keytool -importcert -v -trustcacerts -file“c:\\ BKS / mycrtfile.crt”-alias certificate -keystore“c:\\ BKS / keystore.bks”-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath“c: \\ BKS / prov-jdk15on-146.jar“-storetype BKS -storepass mysecret
讓我們看看這一行是什么(我在這一部分真的很困惑): - “c:\\ BKS / mycrtfile.crt”:這是你的證書的路徑。 - “c:\\ BKS / keystore.bks”這是我們存儲密鑰庫的路徑,您可以更改我使用密鑰庫的輸出名稱,只需確保擴展文件是.bks - “c:\\ BKS /prov-jdk15on-146.jar“:這是我們文件的路徑,可以完成所有工作。 -mysecret:這是使用密鑰庫的密碼,你需要這個密碼,所以不要忘記這一點。
編輯:
4.1-還可以使用此命令行來驗證證書是否已正確導入密鑰庫:
keytool -list -keystore“res / raw / Keystore.bks”-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath“c:\\ BKS / prov-jdk15on-146.jar”-storetype BKS -storepass mysecret
4.2-在此之后你應該看到這樣的輸出:
RootCA,22.10.2010,trustedCertEntry,Thumbprint(MD5):24:77:D9:A8:91:D1:3B:FA:88:2D:C2:FF:F8:CD:33:93 IntermediateCA,22.10.2010, trustedCertEntry,Thumbprint(MD5):98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43
這意味着它是正確導入的。
5.-在此之后,如果你去你的BKS文件夾,你會看到一個Keystore.bks文件,這意味着我們正在路上。
6.-現在讓我們轉到ANDROID部分。 在你的項目中檢查你是否有“raw”文件夾,如果沒有在res下創建這個文件夾,它必須在你的項目/ res / raw中。
7.將Keystore.bks文件復制到raw文件夾中。 現在一切都准備就緒了。
8 .---現在我們將創建一個類來閱讀和信任我們的Keystore:
import java.io.InputStream;
import java.security.KeyStore;
import org.apache.http.conn.ClientConnectionManager;
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.SingleClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import com.futureconcepts.anonymous.R;
import android.content.Context;
public class Client extends DefaultHttpClient {
final Context context;
public Client(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http",
PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(),443));
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams,9000);
HttpConnectionParams.setSoTimeout(httpParams, 9000);
return new SingleClientConnManager(httpParams, registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");//put BKS literal
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in =context.getResources().openRawResource(R.raw.keystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
9.我們現在做了一個請求就是這樣做:HttpClient client = new Client(this); ///設置您的Httpclient。
就是現在你只相信你的證書了。 我希望這個解釋可以幫助您或任何有同樣問題的人。
1)在app / src / main /中創建目錄“assets”
2)將證書放在此目錄中。
3)現在你可以得到InputStream:
InputStream is = this.getAssets().open("mycrtfile.crt");
要使用this.getAssets(),你必須在Activity中,因為在Activity中“this”對應於“Context”。 如果您不在Activity中,則必須將Context(this)作為參數傳遞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.