SSL證書與Https應用部署小結

WWDC 16 中,Apple 表示將繼續在 iOS 10 和 macOS 10.12 里收緊對普通 HTTP 的訪問限制。從 2017 年 1 月 1 日起,所有的新提交 app 默認是不允許使用 NSAllowsArbitraryLoads
來繞過 ATS 限制的,也就是說,我們最好保證 app 的所有網絡請求都是 HTTPS 加密的,否則可能會在應用審核時遇到麻煩。

所以我找到了下面的資料:SSL證書與Https應用部署小結

原文來自:http://han.guokai.blog.163.com/blog/static/136718271201211631456811/

為了提高網站的安全性,一般會在比較敏感的部分頁面采用https傳輸,比如注冊、登錄、控制臺等。像Gmail、網銀等全部采用https傳輸。https/ssl 主要起到兩個作用:網站認證、內容加密傳輸和數據一致性。經CA簽發的證書才起到認證可信的作用,所有有效證書均可以起到加密傳輸的作用。

瀏覽器與SSL證書

SSL應用部署小結 - hanguokai - 韓國愷的博客

上圖是IE和Chrome上對https的不同表現。
Chrome 網站安全性指示器說明:http://support.google.com/chrome/bin/answer.py?hl=zh&answer=95617

SSL最主要應用是在瀏覽器和Web服務器之間,盡管不限于此。當然,安全本身是重要的內在屬性。但在表面上看,部署SSL 就是為了讓用戶瀏覽器里看起來更安全一些,以增加用戶的信任感。所以很多企業更把它當作門面,而簽發機構也為此賣高價,尤其是國內的價格明顯高于國外的。

實際上SSL證書也可以做客戶端認證,用戶擁有自己特有的證書,用它可以證明自己的身份,當然也就用不著用戶名和密碼了。但這種用的很少,一般web服務器也不支持。

內容加密傳輸更安全,如果只是為了加密,使用自簽發的證書也可以,但瀏覽器無法驗證證書,所以會給出一個非常嚇人的警告,所以自簽發證書不適合給外人使用,只適合內部使用,把這個證書 加入到自己的信任列表或忽略證書驗證即可,以后就不會繼續攔截了。

證書需要被少數一級或二級 CA 認證才有效。計算機安全中的信任就是一個信任鏈的關系,信任鏈最頂端的被稱為根證書。
自簽發的證書在技術上是完全一樣的,僅用于加密傳輸是沒問題的。但是不能被外人信任,所以一般僅用于內部使用。除了自簽發不被信任,如果證書過期、已被吊銷或者非證書所代表的域名也都是不被信任的,導致證書驗證出錯。

用于網站的證書需要被大眾信任,所以不能自簽發的證書,那就申請(購買)一個吧。

申請證書

1.證書類別

按證書包含域名數量分為:
單域名:只針對這個域名有效,不能用在其它域名下。
多域名:只針對列出的多個域名有效。
通配符域名(wildcard):對任意子域名有小,顯示的是 *.example.com。

注意:SSL所說的單個域名是一個完整的域名,一個子域名就算一個,而非一個頂級域名。
如果網站有很多子域名,只需要申請真正需要的域名證書。

按驗證的類別分:
域名認證(Domain Validation):認證你的域名所有權和網站,申請驗證簡單,幾分鐘即可。
組織機構認證(Organization Validation):認證的域名和公司信息,需要提交公司資料認證。
擴展認證(Extended Validation,簡稱EV):這種證書會在瀏覽器中出現“很明顯”的綠色地址欄,給用戶的可信度最高。有安全評估保證。

個人或小站點可用一類或二類,企業一般用二類認證,少數企業會用到EV認證。

2. 證書價格

看了看網上SSL證書的價格,便宜的一般都是10美元左右一個子域名/每年,按不同類別、不同品牌等價格在幾十美元到幾百美元一年。比如能顯示綠色地址欄的EV證書和通配符證書貴一些。國內自己的或代理的,比國外貴不少,動輒幾千元。其實就是由可信源認證了一下,類似于辦證,用起來沒什么差別,并非越貴越好。

3. 簽發機構(“賣家”)

SSL應用部署小結 - hanguokai - 韓國愷的博客

國外常見的SSL提供商有:Thawte,Go Daddy,VeriSign,RapidSSL,GeoTrust(QuickSSL),StartSSL,Comodo。
StartSSL、Go Daddy的比較便宜,GeoTrust、Comodo的價格適中,Thawte和VeriSign的價格較貴。

VeriSign現在歸屬賽門鐵克,在國內是由天威誠信代理的。世界真小,天威誠信就在我很多年以前的東家(啟明星辰)大樓里,地下一層是他們的機房,我還進去過一次。

4. 免費的StartSSL

唯一免費的是StartSSL,其它的一般只提供30免費試用。

但 StartSSL 提供的免費證書是一類的、僅對域名和email進行驗證,不對組織做驗證(也就是面向自然人的,非面向組織機構的),不過
僅作為域名驗證和數據加密也夠了,并且瀏覽器也認它,一般人也不會去看你的證書級別。適合個人和初創網站使用,以后有錢了再申請個收費的替換即可。

我很順利地申請到了免費的StartSSL證書,分別用在兩個子域上。

最后,證書簽發給你后,最主要是保護好私鑰證書,這個丟失或泄漏就完了。因為如果被別人利用也就毫無安全性了,需要向證書簽發機構申請撤銷證書并申請新的證書,這當然也是要收費的。

應用規劃、配置和調整

并不是說有了SSL證書就沒事了,還要考慮應用中的使用問題,需要規劃、服務器配置、應用調整等多個環節。

SSL比 http 要消耗更多cpu資源(主要是在建立連接的階段,之后還要對內容加密),所以對一般網站,只需要對部分地方采用https,大部分開放內容是沒必要的,具體取決于你的業務要求。比如對于很多安全要求較低的網站,完全不用https也是可接受的。

某些頁面是同時支持 http 和 https ,還是只支持 https、強制 https?
同時支持就是用戶用什么協議訪問都可以,那么用戶的請求主要就是由頁面本身的鏈接引導來的,因為一般用戶不會自己特意去修改地址欄的。
一般我們的網站可以做成同時支持http和https,都可以訪問。但是這就容易有后面說的混合內容或混合腳本的問題。

還可以規劃為部分頁面支持 https,一般公開頁面不用https,只是將部分地方的鏈接改為 https 就可以了。專門期望以 https 訪問的頁面中,引用的絕對URL可以明確的使用 https鏈接。

是否強制 https ?對于安全性高的網站或網站中的部分頁面,可以強制使用https訪問, 即使用戶在地址欄里手工把 https 改為 http, 也會被自動重定向回 https 上。比如可以通過配置web服務器 rewrite 規則將這些 http url 自動重定向到對應的 https url 上(這樣維護比較簡單),而不用改應用。

解決混合內容問題(
****http和https)

混合內容是指:在https的頁面中混合了非https的資源請求,比如圖片、css、js 等等。如果是混合了非 https 的 js 代碼,則被稱為混合腳本。
混合內容的危害:如果只是混合了不安全的圖片和css,那么受中間人攻擊篡改,一般只會影響頁面的顯示,危害相對小一點。如果是混合了不安全的 js 代碼,則這個不安全的 js 可以完全訪問和修改頁面中的任何內容,這是非常危險的。

另請參看,Chrome對混合腳本危害的說明與提示:Trying to end mixed scripting vulnerabilities

所以,只有頁面本身和所有引用的資源都是 https 的瀏覽器才認為是安全的,只要其中引用了非安全資源(即使圖片),瀏覽器都會給出不安全的提示,特別是有 js 的情況。如果瀏覽器提示不安全,那樣我們就達不到原來目的了。我們費了半天功夫去申請 SSL 證書,配置Web服務器,最后如果因為混合內容而前功盡棄就太糟了。咱繼續努力吧,想辦法讓所有引用資源都是安全的。

理論上,混合了第三方的內容,即使是SSL的第三方內容也不是很好。因為用戶信任的是你,而不是第三方,即使第三方也支持https,但你能保證第三方就絕對安全嗎。不引用任何第三方才是絕對安全的,但這樣太嚴格了,安全其實也是一個 tradeoff 的問題,需要考慮很多方面的平衡。還好,起碼現在瀏覽器認為已經是安全的了。

引用第三方文件的問題(如 CDN 分發的文件)

簡單地說,這個問題要么有第三方提供 https 支持,要么不用它(用自己本地的)。

一般我們會引用由 CDN 分發的文件,比如某個 js 庫文件,而不用訪問自己網站上的,這樣借助 CDN 網絡可以加快速度,這當然很好。
但是,如果我們在頁面中使用絕對 URL 直接引用這個文件就無法自動使用 https 了!出現了混合協議內容,瀏覽器又該“變臉”了。

當SSL 遇上CDN 或 其它第三方文件就有點麻煩,因為很多CDN還不支持SSL。如果支持 https 的話就可以直接用 https 的絕對URL了,即使是同時支持http 和 https 的頁面,這樣做也不算太浪費,起碼解決了問題。

因為CDN的云文件提供者,一般為每個cdn用戶創建一個單獨的子域名來使用,這樣的話,CDN提供者要想支持 https 就必須支持所有可能的子域名,因此要求CDN提供方使用那種通配符子域名的證書。

相對 URL、絕對 URL 與 只缺協議的URL(****Protocol Relative URL****)
相對路徑比較簡單,自動匹配用戶請求的 http 或 https 協議。

但是絕對 url 則不成,因為絕對 url 已經明確地寫上了協議: http://www.example.com/jquery.js
這個問題還有一個辦法解決,你一定沒見過這種形式:** //www.example.com/jquery.js**
哈哈,一個缺少協議的URL(實際上還算是相對URL),這種形式可以在瀏覽器中被正確補充上合適的協議!很多人都用這種方法。
但是,這里有點小問題,IE7 和 IE8 處理這種缺少協議的URL的css 文件時,同一個css文件會下載兩次,詳見Steve的文章

JS 自動判斷當前協議
現在我們經常用 js 來加載其它 js 文件或 其它別的文件,如果是請求是相對URL則沒問題,如果是絕對URL怎么辦?
其實 js 腳本可以這樣:document.location.protocol 等于 'http:' 還是 'https:' 來判斷。例如在 Google Analytics 的嵌入代碼中:
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';

應用程序中如何判斷訪問協議
對于動態頁面,如 jsp、php等,也是可以動態判斷當前是否使用了 https 協議的。所以應用可以根據動態判斷,來生成不同的引用 URL。這樣雖然有點麻煩,但也算是解決了自動識別協議的問題,當然相對路徑總是不需要處理的。
比如在 jsp 中:
request.isSecure() 為true 表示當前為 https ,false表示 http 訪問
request.getScheme() 返回字符串 https 或 http

注意,如果 tomcat 部署在其它web服務器代理的后面,需要正確配置好才能返回正確結果,見本文最后一部分。

同源策略的問題
最后提醒一點:http 和 https是不同源的!即使后面的內容都一樣。所以 ajax 發請求的時候要使用正確協議的絕對URL才行。
相對URL的 ajax 請求沒關系。

**Nginx 配置
**
小結一下 Nginx 配置SSL注意的問題,詳細安裝配置內容請參考其它資料,如官方 SSL模塊https配置文檔
1. 首先檢查一下是否已安裝了 SSL模塊,因為默認是不包含的。

用 nginx -V 命令檢查一下。如果沒有ssl模塊則需要重新安裝(建議升級到最新版本),注意安裝時加上ssl 選項:
./configure --with-http_ssl_module

另外,nginx需要依賴 openssl 提供ssl支持,這個也要有。

2. nginx.conf 中的典型配置示例
listen 80;
listen 443 ssl;
ssl_certificate cert.pem; #修改具體文件
ssl_certificate_key ssl.key; #修改具體文件

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;

上面第2-4項是關鍵。這些配置放在 server 塊就可以對其中的所有 location 生效了,并且同時支持 http 和 https 。或者把 http 和 https 分開配置也很常見。

3. 合并證書配置文件
和Apache配置不同,Nginx需要將服務器證書和ca證書鏈合并到一個文件中,作為 ssl_certificate 配置的內容。
例如,按照證書鏈從下向上的順序,我有三個證書:
ssl.crt(自己域名的服務器證書)
sub.class1.server.ca.pem(startssl 的一類證書)
ca.pem(startssl 的根證書)

把它們的內容按順序連接到的一個文件中,每個內容另起一行,中間沒有空行或空格。

4. 避免啟動時輸入密碼
配好之后,啟動nginx 要你輸入密鑰的密碼。這是因為 ssl_certificate_key 配置對應的文件(也就是 startssl 給你的私鑰文件)內容是加密的,需要輸入你創建這個時設置的密碼才能解密。這樣私鑰雖然很安全,但是每次重啟服務都要輸入一次密碼也太麻煩了。其實,只要證書改為解密了的內容,就可以避免每次輸入密碼。用如下命令即可:
openssl rsa -in ssl.key -out newssl.key 輸入密碼,就生成了解密后的私鑰內容,使用這個就OK了。

但是就像前面說的,一定要在服務器上保護好它,例如:
chmod 400 ssl.key (僅root可讀)

5. 優化SSL配置
SSL 很消耗 CPU 資源,尤其是在建立連接的握手階段。一是通過開啟 keepalive 可以重用連接。二是可以重用和共享ssl session,見上面ssl_session相關配置。

**獨立Tomcat+SSL
**
Tomcat 是很常見的 Java應用服務器,當然也可以作為獨立的 Web服務器,所有用戶請求直接訪問 tomcat。

如果 Tomcat 作為獨立的Web服務器,那么就需要配置Tomcat就可以了,文檔參考這里這個。主要是配置存放證書的 Keystore 和 連接器Connector。

Java的keystore
keystore 是 Java 中專用并內置的一個類似于 openssl 的工具,一個 keystore 文件就是一個“保險箱”(database),專門存放證書和密鑰,和相關的管理功能:生成自簽發的證書、密鑰、導入導出等。可以通過 keytool 命令或 Java api 交互。

利用keytool 命令將你的證書導入進去。

Tomcat中Connector
tomcat中有三種 Connector 實現:block、nio 和 APR。前兩者使用Java SSL(這需要 keystore 的配置 ),APR使用OpenSSL(不需要用keystore,直接指定證書),配置略有不同。

**Nginx+Tomcat+SSL
**
實際上,大規模的網站都有很多臺Web服務器和應用服務器組成,用戶的請求可能是經由 Varnish、HAProxy、Nginx之后才到應用服務器,中間有好幾層。而中小規模的典型部署常見的是 Nginx+Tomcat 這種兩層配置,而Tomcat 會多于一臺,Nginx 作為靜態文件處理和負載均衡。

如果Nginx作為前端代理的話,則Tomcat根本不需要自己處理 https,全是Nginx處理的。用戶首先和Nginx建立連接,完成SSL握手,而后Nginx 作為代理以 http 協議將請求轉給 tomcat 處理,Nginx再把 tomcat 的輸出通過SSL 加密發回給用戶,這中間是透明的,Tomcat只是在處理 http 請求而已。因此,這種情況下不需要配置 Tomcat 的SSL,只需要配置 Nginx 的SSL 和 Proxy。

在代理模式下,Tomcat 如何識別用戶的直接請求(URL、IP、https還是http )?
在透明代理下,如果不做任何配置Tomcat 認為所有的請求都是 Nginx 發出來的,這樣會導致如下的錯誤結果:
request.getScheme() //總是 http,而不是實際的http或https
request.isSecure() //總是false(因為總是http)
request.getRemoteAddr() //總是 nginx 請求的 IP,而不是用戶的IP
request.getRequestURL() //總是 nginx 請求的URL 而不是用戶實際請求的 URL
response.sendRedirect( 相對url ) //總是重定向到 http 上 (因為認為當前是 http 請求)

如果程序中把這些當實際用戶請求做處理就有問題了。解決方法很簡單,只需要分別配置一下 Nginx 和 Tomcat 就好了,而不用改程序。

配置 Nginx 的轉發選項:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

配置Tomcat server.xml 的 Engine 模塊下配置一個 Value:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>

配置雙方的 X-Forwarded-Proto 就是為了正確地識別實際用戶發出的協議是 http 還是 https。X-Forwarded-For 是為了獲得實際用戶的 IP。
這樣以上5項測試就都變為正確的結果了,就像用戶在直接訪問 Tomcat 一樣。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容