SSL證書與Https應用部署小結

爲了提升網站的安全性,通常會在比較敏感的部分頁面採用https傳輸,好比註冊、登陸、控制檯等。像Gmail、網銀等所有采用https傳輸。php

https/ssl 主要起到兩個做用:網站認證、內容加密傳輸和數據一致性。經CA簽發的證書才起到認證可信的做用,全部有效證書都可以起到加密傳輸的做用。
 
 
瀏覽器與SSL證書
SSL應用部署小結 - hanguokai - 韓國愷的博客
上圖是IE和Chrome上對https的不一樣表現。
 
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 配置的內容。
例如,按照證書鏈從下向上的順序,我有三個證書:
  1. ssl.crt(本身域名的服務器證書)
  2. sub.class1.server.ca.pem(startssl 的一類證書)
  3. 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 同樣。
 
http://han.guokai.blog.163.com/blog/static/136718271201211631456811/
相關文章
相關標籤/搜索