成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

[轉(zhuǎn)]https配合移動(dòng)端開發(fā)

Render / 746人閱讀

摘要:而且文章經(jīng)過統(tǒng)計(jì)發(fā)現(xiàn)的應(yīng)用程序沒有正確地在通信過程中進(jìn)行證書驗(yàn)證。確認(rèn)服務(wù)器端證書的和代碼中的證書主體一致。根據(jù)開發(fā)安全的應(yīng)用提出的觀點(diǎn),可以避免最終用戶證書有效期可能比較短的問題。

轉(zhuǎn)載請(qǐng)注明出處 http://www.paraller.com
原文排版地址 點(diǎn)擊獲取更好閱讀體驗(yàn)

轉(zhuǎn)載:http://xhrwang.me/2015/06/06/https-and-android.html 部分修改

背景

Google 在 Android 6.0 Changes 中聲稱在 Android 6.0 系統(tǒng)中,移除了 Apache HttpClient 組件“

Android 6.0 release removes support for the Apache HTTP client. If your app is using this client and targets Android 2.3 (API level 9) or higher, use the HttpURLConnection class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle file:

所以,為了適配最新的 Android 6.0 系統(tǒng),作為開發(fā)者,如果之前使用了 Apache HttpClient 開發(fā)的網(wǎng)絡(luò)通信模塊,是時(shí)候使用 URLConnection 以及 Derived 類型來重新實(shí)現(xiàn),畢竟調(diào)整后能得到上面 Google 提到的各種好處,而且不需要依賴一個(gè)額外的包。

在我們使用智能移動(dòng)設(shè)備的時(shí)候,很多時(shí)候我們可能處于不安全的 Wifi 環(huán)境中,考慮到用戶數(shù)據(jù)在傳輸過程中的安全性,Https 協(xié)議越來越成為網(wǎng)絡(luò)通信的主流,但是使用 Https 的時(shí)候如果實(shí)現(xiàn)有誤,還是避免不了 MITMA (Man in the middle attack),國(guó)外有篇論文 Detection of SSL-related securityvulnerabilities in Androidapplications 對(duì)這種情況作了很好的總結(jié),推薦大家看看。而且 SSL Vulnerabilities at Large 文章經(jīng)過統(tǒng)計(jì)發(fā)現(xiàn) 73% 的 Android 應(yīng)用程序沒有正確地在 Https 通信過程中進(jìn)行證書驗(yàn)證。

這篇文章就是想討論一下如何正確地使用 HttpsURLConnection 實(shí)現(xiàn) Https 通信。除了本文,Android security - Implementation of Self-signed SSL certificate for your App. 也非常推薦,但遺憾的是該文最后給出的完整實(shí)例使用了 Apache HttpClient 的實(shí)現(xiàn)方式,不過該文對(duì) Android 應(yīng)用開發(fā)中如何正確處理 Https 通信做了非常好的分析。

Https 證書 證書鏈(Certificate Chains)

我們一般常見的證書鏈分為兩種:

二級(jí)證書:直接由 受信任的根證書頒發(fā)機(jī)構(gòu) 頒發(fā)的證書(CRT 文件),由于這種情況下一旦 Root CA 證書遭到破壞或者泄露,提供這個(gè) Certificate Authority 的機(jī)構(gòu)之前頒發(fā)的證書就全部失去安全性了,需要全部換掉,對(duì)這個(gè) CA 也是毀滅性打擊,現(xiàn)在主流的商業(yè) CA 都提供三級(jí)證書。

三級(jí)證書:由 受信任的根證書頒發(fā)機(jī)構(gòu) 下的 中級(jí)證書頒發(fā)機(jī)構(gòu) 頒發(fā)的證書,這樣 ROOT CA 就可以離線放在一個(gè)物理隔離的安全的地方,即使這個(gè) CA 的中級(jí)證書被破壞或者泄露,雖然后果也很嚴(yán)重,但根證書還在,可以再生成一個(gè)中級(jí)證書重新頒發(fā)證書,而且這種情況對(duì) HTTPS 的性能和證書安裝過程也沒有太大影響,這種方式也基本成為主流做法。

我們的互聯(lián)網(wǎng)就是運(yùn)行在這個(gè)基于信任關(guān)系的基礎(chǔ)上,國(guó)際上的 受信任的根證書頒發(fā)機(jī)構(gòu) 是有限的幾個(gè)機(jī)構(gòu),具體信息可以參考 維基百科的介紹。

如何獲得可用于 HTTPS 的證書

生成 openssl 生成一個(gè)私鑰:

生成使用 RSA 非對(duì)稱加密類型的私鑰,使用 DES3 算法,輸出 OpenSSL 格式,采用 2048 位強(qiáng)度。server.key是文件名,生成過程需要提供一個(gè)至少四位的密碼。
openssl genrsa -des3 -out server.key 2048

在部署支持 HTTPS 網(wǎng)站的時(shí)候 Web Server 每次啟動(dòng)都需要提供使用的私鑰密碼,可以使用下面的命令去除剛生成的私鑰密碼:

openssl rsa -in server.key -out server_nopwd.key

生成 CSR (Certificate Signing Request)文件:

openssl req -new -key server_nopwd.key -out server.csr

在這個(gè)過程中需要提供像國(guó)家、地區(qū)、組織名稱以及 E-mail 等信息,對(duì)于用于 HTTPS 的 CSR 來說,Common Name 必須和網(wǎng)站域名一致,以便之后進(jìn)行 Host Name 校驗(yàn),所以 Common Name 的選擇比較重要,可以選擇 Single Name 或者 WildCard 類型的,二者區(qū)別可見 Choosing the SSL Certificate Common Name。上面的命令執(zhí)行時(shí)會(huì)需要輸入一些信息:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BJ
Locality Name (eg, city) []:BJ 
Organization Name (eg, company) [Internet Widgits Pty Ltd]:OrgName
Organizational Unit Name (eg, section) []:OrgUnit
Common Name (eg, YOUR name) []:www.DOMAIN.com
Email Address []:Name@DOMAIN.com

生成 CRT 證書文件

Self-Signed Certificate 自簽名證書,如果只是用于比如應(yīng)用 API 接口,不需要用于可通過瀏覽器訪問的網(wǎng)頁(yè)展示,為了節(jié)省開支或者僅僅是內(nèi)部使用可以考慮。

openssl x509 -req -days 365 -in server.csr -signkey server_nopwd.key -out server.crt

提交 CSR 文件并購(gòu)買授信中級(jí)證書機(jī)構(gòu)頒發(fā)的證書

openssl x509 -md5 -days 3560 -req -CA ca.crt -CAkey ca.key -CAcreateserial -CAserial ca.srl -in server.csr -out server.crt

有的 CA 簽名后會(huì)提供兩個(gè) CRT 文件,一個(gè)是對(duì)提交的 CSR 文件簽名后的 CRT,一個(gè)是 CA 自己的 Intermediate CRT 文件,這個(gè) CRT 文件是公開的,比如 Symantic 的常見 Intermediate CRT 就可以從 Symantec Class 3 Secure Server CA - G4 下載到,GoDaddy 的所有不同格式的 CRT 文件都公開在 GoDaddy Repository,為了讓配置的 Https 網(wǎng)站被瀏覽器認(rèn)為是可信的,這兩個(gè) CRT 文件可以合并后配置到 Web Server 中,這相當(dāng)于在 Web Server 服務(wù)器上安裝了該 CA 的 Intermediate CRT 證書。合并方式可以參考 How do I make my own bundle file from CRT files?

使用 CRT 文件和 私鑰配置 HTTPS 網(wǎng)站服務(wù)

這里的具體操作方式取決于使用的 Web Server 類型,比如 Apache 和 Nginx 有自己的配置方法,就不列了,各個(gè) Web Server 的文檔都有詳細(xì)說明,GoDaddy 的文檔 INSTALL SSL CERTIFICATES 對(duì)主流的 Web Server 如何進(jìn)行 Https 配置作了非常全面的總結(jié)。

Https 網(wǎng)站

這里我們可以使用一個(gè)可用于測(cè)試的 Python Flask 實(shí)現(xiàn)的 Https Web Server:

from OpenSSL import SSL
from flask import Flask
from flask import render_template

app = Flask(__name__)
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file("/Users/rwang/testssl/test.key")
context.use_certificate_file("/Users/rwang/testssl/test.crt")

@app.route("/")
def hello():
  return "Howdy, there!", 200 

if __name__ == "__main__":
  app.run(host="127.0.0.1",port=8443, 
      debug = True, ssl_context=context)

啟動(dòng)這個(gè)測(cè)試服務(wù)器,就可以從瀏覽器中通過 https://127.0.0.1:8443 這個(gè)地址訪問了,如果你使用了 Self signed Certificate,瀏覽器會(huì)提示危險(xiǎn),選擇仍然繼續(xù)就可以看到 Howdy, there! 的歡迎語(yǔ)了。注意,如果需要通過在同一個(gè)局域網(wǎng)內(nèi)的 Android 設(shè)備訪問這個(gè)測(cè)試服務(wù)器,請(qǐng)把 127.0.0.1 替換為本機(jī)在局域網(wǎng)內(nèi)的 ip。

HttpsURLConnection

這里分兩種情況來討論。

使用 Self signed Certificate
自簽名證書可以用于 Android 應(yīng)用程序的 Api 接口通信中,按照 Certificate pinning with self-singed certificate 的說法,有下面的有點(diǎn):

Increased security - with pinned SSL certificates, the app is independent of the device’s trust store. Compromising the hard coded trust store in the app is not so easy - the app would need to be decompiled, changed and then recompiled again - and it can’t be signed using the same Android keystore that the original developer of the app used.

  **Reduced costs** - SSL certificate pinning gives you the possibility to use a self-signed certificate that can be trusted. For example, you’re developing an app that uses your own API server. You can reduce the costs by using a self-signed certificate on your server (and pinning that certificate in your app) instead of paying for a certificate. Although a bit convoluted, this way, you’ve actually improved security and saved yourself some money.

當(dāng)然,文中也提到使用自簽名證書也有不足的地方:

Less flexibility - when you do SSL certificate pinning, changing the SSL certificate is not that easy. For every SSL certificate change, you have to make an update to the app, push it to Google Play and hope the users will install it.

使用自簽名證書,需要自定義 TrustManager

class MyTrustManager implements X509TrustManager {
          X509Certificate cert;
          MyTrustManager(X509Certificate cert) {
              this.cert = cert;
          }
          @Override
          // for server only
          public void checkClientTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
              // 我們?cè)诳蛻舳酥蛔龇?wù)器端證書校驗(yàn)。
          }
          @Override
          // only trust the given certificate or certificate issued by it
          public void checkServerTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
              // 確認(rèn)服務(wù)器端證書和代碼中 hard code 的 CRT 證書相同。
              if (chai[0].equals(this.cert)){
                  if(Utils.DEBUG){
                      Log.i(Utils.DEBUG_TAG, "checkServerTrusted Certificate from server is valid!");
                  }
                  return;// found match
              }
              throw new CertificateException("checkServerTrusted No trusted server cert found!");
          }
          @Override
          public X509Certificate[] getAcceptedIssuers() {
              return new X509Certificate[0];
          }
      }

然后使用其定義 SSLContext 實(shí)例:

SSLContext sc = SSLContext.getInstance("TLS");
      TrustManager tm = new MyTrustManager(readCert(certStr));
      sc.init(null, new TrustManager[]{
              tm
      }, null);
    `
其中,`readCert` 方法的實(shí)現(xiàn)為:
`  private static X509Certificate readCert(String cer) {
          if (cer == null || cer.trim().isEmpty())
              return null;
          InputStream caInput = new ByteArrayInputStream(cer.getBytes());
          X509Certificate cert = null;
          try {
              CertificateFactory cf = CertificateFactory.getInstance("X.509");
              cert = (X509Certificate) cf.generateCertificate(caInput);
          } catch (Exception e) {
              if (Utils.DEBUG) {
                  e.printStackTrace();
              }
          } finally {
              try {
                  if (caInput != null) {
                      caInput.close();
                  }
              } catch (Throwable ex) {
              }
          }
          return cert;
      }

最后使用 HttpsURLConnection 進(jìn)行網(wǎng)絡(luò)通信:

HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();      conn.setSSLSocketFactory(sc.getSocketFactory());
      // By default, this implementation of HttpURLConnection requests that servers use gzip compression
      // and it automatically decompresses the data for callers of getInputStream().
      // The Content-Encoding and Content-Length response headers are cleared in this case.
      // Gzip compression can be disabled by setting the acceptable encodings in the request header:
      // http://developer.android.com/reference/java/net/HttpURLConnection.html
      conn.setRequestProperty("Accept-Encoding", "");
      StringBuffer response = new StringBuffer();
      OutputStream os = null;
      BufferedReader rd = null;
      InputStream is = null;
      int statusCode = -1;
      try {
          conn.setRequestMethod("POST");
          os = conn.getOutputStream();
          os.write(payload);
          os.close();
          // Get Response
          statusCode = conn.getResponseCode();
          InputStream is;
          if(statusCode > HttpURLConnection.HTTP_BAD_REQUEST){
              is = conn.getErrorStream();
          }else{
              is = conn.getInputStream();
          }
          rd = new BufferedReader(new InputStreamReader(is));
          String line;
          while ((line = rd.readLine()) != null) {
              response.append(line);
              response.append("
");
          }
      } catch (Throwable e) {
          if (Utils.DEBUG) {
              e.printStackTrace();
          }
      } finally {
          try {
              if (is != null) {
                  is.close();
              }
          } catch (Throwable ex) {
          }
          try {
              if (os != null) {
                  os.close();
              }
          } catch (Throwable ex) {
          }
          try {
              if (rd != null) {
                  rd.close();
              }
          } catch (Throwable ex) {
          }
          try {
              if (conn != null) {
                  conn.disconnect();
              }
          } catch (Throwable ex) {
          }
      }

需要注意的是:

conn.setRequestProperty(“Accept-Encoding”, “”); 如果自己實(shí)現(xiàn)了壓縮算法,不希望系統(tǒng)自動(dòng)添加 gzip 壓縮的話必須添加。詳情請(qǐng)參考上面代碼注釋中的文檔。

conn.setSSLSocketFactory(sc.getSocketFactory()); 這樣設(shè)置后,自定義的 SSLContext 將被用于本次 Https 通信,不會(huì)影響應(yīng)用中其他可能的 Https 通信。

使用經(jīng)過 CA 認(rèn)證的證書

如果服務(wù)器端正確配置了使用 CA 認(rèn)證后的證書,Android 客戶端應(yīng)用程序可以直接使用 `HTTPSURLConnection` 訪問:

URL url = new URL("https://www.example.com/");      HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();      InputStream in = urlConnection.getInputStream();

如果需要做更嚴(yán)格的驗(yàn)證,也可以這樣自定義 TrustManager

class MyTrustManager implements X509TrustManager {
          X509Certificate cert;
          MyTrustManager(X509Certificate cert) {
              this.cert = cert;
          }
          @Override
          // for server only
          public void checkClientTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
              // 我們?cè)诳蛻舳酥蛔龇?wù)器端證書校驗(yàn)。
          }
          @Override
          // only trust the given certificate or certificate issued by it
          public void checkServerTrusted(X509Certificate[] chain, String authType)
                  throws CertificateException {
              // 確認(rèn)服務(wù)器端證書的 Intermediate CRT 和代碼中 hard code 的 CRT 證書主體一致。
              if (!chain[0].getIssuerDN().equals(certificate.getSubjectDN())) {
                  throw new CertificateException("Parent certificate of server was different than expected signing certificate");
              }
              try {
                  // 確認(rèn)服務(wù)器端證書被代碼中 hard code 的 Intermediate CRT 證書的公鑰簽名。
                  chain[0].verify(certificate.getPublicKey());
                  // 確認(rèn)服務(wù)器端證書沒有過期
                  chain[0].checkValidity();
              } catch (Exception e) {
                  throw new CertificateException("Parent certificate of server was different than expected signing certificate");
              }
          }
          @Override
          public X509Certificate[] getAcceptedIssuers() {
              return new X509Certificate[0];
          }
      }

思路就是在代碼中 hard code CA 認(rèn)證后交付的 Intermediate CRT 文件作為客戶端證書對(duì)服務(wù)器端證書進(jìn)行校驗(yàn)。根據(jù) 開發(fā)安全的Android應(yīng)用 提出的觀點(diǎn),可以避免最終用戶證書有效期可能比較短的問題。

注釋:
證書失效可以根據(jù)Intermediate CRT 重新續(xù)期

之后使用 HttpsURLConnection 的方式和使用自簽名證書時(shí)相同就不特別說明了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/11304.html

相關(guān)文章

  • 【技術(shù)】移動(dòng)適配 px2rem/px2vw 的原理與實(shí)現(xiàn)

    摘要:不同的前端框架,配合等打包工具,可以更高效的使用這些插件,完成移動(dòng)端適配的配置工作。 簡(jiǎn)介 【目標(biāo)】:前端開發(fā)移動(dòng)端及H5時(shí)候,不需要再關(guān)心移動(dòng)設(shè)備的大小,只需要按照固定設(shè)計(jì)稿的px值布局!【基礎(chǔ)】 dpr(設(shè)備像素比)css的像素px不等于設(shè)備像素/分辨率/各種值,css的px可以簡(jiǎn)單理解為虛擬像素,與設(shè)備無(wú)關(guān),css的px需要乘dpr計(jì)算為設(shè)備像素; css3 的 rem,即ro...

    AlexTuan 評(píng)論0 收藏0
  • Vue Transition 實(shí)現(xiàn)類原生組件跳轉(zhuǎn)過渡動(dòng)畫

    摘要:官方文檔演示地址請(qǐng)?jiān)谝苿?dòng)端查看,端查看請(qǐng)打開移動(dòng)端調(diào)試模式前言看了挺多的框架都不帶過渡動(dòng)畫,今天心血來潮,就把自己平時(shí)用的動(dòng)效抽離出來。原理模版中使用了提供的封裝組件,配合類名在的六種不同的狀態(tài)過渡中切換。 官方文檔:https://cn.vuejs.org/v2/guide... 演示地址:http://www.coderlife.com (請(qǐng)?jiān)谝苿?dòng)端查看,PC端查看請(qǐng)打開移動(dòng)端調(diào)試...

    whatsns 評(píng)論0 收藏0
  • 轉(zhuǎn):CSS :placeholder-shown偽類實(shí)現(xiàn)Material Design占位符交互效果

    摘要:轉(zhuǎn)自偽類實(shí)現(xiàn)占位符交互效果一規(guī)范中占位符交互效果風(fēng)格占位符交互效果官方示意見此頁(yè)面。我們可以采用絕對(duì)定位最后,對(duì)這個(gè)元素在輸入框時(shí)候,以及非顯示的時(shí)候進(jìn)行重定位縮小并位移到上方四清除按鈕部分上是必要屬性,配合偽類實(shí)現(xiàn)我們的效果。 轉(zhuǎn)自: https://github.com/yougola/bl... CSS :placeholder-shown偽類實(shí)現(xiàn)Material Design占...

    gaara 評(píng)論0 收藏0
  • 、后、運(yùn)維都能用的動(dòng)態(tài)json數(shù)據(jù)管理神器,節(jié)省你大量的開發(fā)、設(shè)計(jì)數(shù)據(jù)庫(kù)、運(yùn)維的時(shí)間

    摘要:基于的動(dòng)態(tài)數(shù)據(jù)管理神器介紹什么是基于模塊化的動(dòng)態(tài)數(shù)據(jù)管理平臺(tái)。什么是用于動(dòng)態(tài)生成表單的,參考使用案例官方文檔使用場(chǎng)景有哪些無(wú)論前端后端移動(dòng)端運(yùn)維,理論上所有需要?jiǎng)討B(tài)配置數(shù)據(jù)的場(chǎng)景都可以使用。針對(duì)運(yùn)維可以作為區(qū)分環(huán)境的配置中心等。 基于Json Schema的動(dòng)態(tài)數(shù)據(jù)管理神器-DMS 介紹 什么是DMS? DMS Github:基于Json Schema/UI Schema模塊化的Jso...

    canopus4u 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<