整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          一招杜絕 - 網(wǎng)站被劫持強(qiáng)制植入廣告的問題

          一招杜絕 - 網(wǎng)站被劫持強(qiáng)制植入廣告的問題

          我們?nèi)粘I暇W(wǎng)過程中,經(jīng)常會(huì)遇到打開一個(gè)網(wǎng)頁,網(wǎng)頁都還沒有顯示出來,一堆廣告就彈出來的現(xiàn)象。或者網(wǎng)頁剛剛打開,沒幾分鐘 就會(huì)彈出來某游戲廣告,注冊(cè)領(lǐng)豪華坐騎等等的小廣告。這些廣告不僅僅會(huì)讓我們對(duì)網(wǎng)站的真實(shí)性產(chǎn)生懷疑,另外一方面也會(huì)大大影響訪問瀏覽網(wǎng)頁時(shí)的觀感。

          網(wǎng)頁被劫持強(qiáng)加廣告的亂像在互聯(lián)網(wǎng)上很常見,對(duì)網(wǎng)站管理員和用戶訪問來說都會(huì)造成困擾。這種問題通常是運(yùn)營(yíng)商進(jìn)行http劫持所導(dǎo)致的,要解決運(yùn)營(yíng)商劫持的問題,將http協(xié)議升級(jí)成為https協(xié)議是一種非常有效的方式

          如何將http協(xié)議升級(jí)成https協(xié)議

          HTTPS的工作原理主要是在HTTP的基礎(chǔ)上加入了SSL/TLS協(xié)議,用于對(duì)數(shù)據(jù)傳輸進(jìn)行加密處理,從而防止數(shù)據(jù)被第三方竊取和篡改。相較于傳統(tǒng)的HTTP,HTTPS提供了更加可靠的信息安全保護(hù)措施。

          打開SSL證書服務(wù)商,如DigiCert、GlobalSign、GeoTrust。像國產(chǎn)JoySSL證書服務(wù)商可以提供免費(fèi)的SSL證書供個(gè)人用戶,企業(yè)用戶,政務(wù)機(jī)構(gòu)等等的使用和申請(qǐng)。

          以國產(chǎn)JoySSL申請(qǐng)SSL證書為例,打開JoySSL官網(wǎng),用手機(jī)或者微信掃碼注冊(cè)登錄,填寫注冊(cè)碼230921。在證書選擇時(shí)選擇需要的SSL證書。

          PC打開JoySSL官網(wǎng),填寫注冊(cè)碼230921,即可免費(fèi)申請(qǐng)SSL證書,解決強(qiáng)制廣告植入問題。

          https://www.joyssl.com/certificate/select/free.html?nid=21

          在申請(qǐng)證書時(shí),選擇需要的證書類型,如網(wǎng)站只有一個(gè)域名就申請(qǐng)單域名證書,如果網(wǎng)站有多個(gè)域名,可以申請(qǐng)多域名證書或者通配符證書,等等。

          申請(qǐng)證書過程中需要填寫所需要保持的域名,有部分證書還需要填寫單位信息,聯(lián)系人,郵箱等等,按步驟申請(qǐng)即可,要注意的是域名等等信息的填寫正確

          證書申請(qǐng)之后對(duì)所需要保護(hù)的域名進(jìn)行驗(yàn)證,簽發(fā),以及后面的部署工作,這個(gè)部分因?yàn)槊總€(gè)域名的web環(huán)境不同,可以按web環(huán)境下安裝證書的教程來操作,如果不會(huì)操作也可以直接聯(lián)系客服處理。

          層出不窮的頁面小廣告

          在互聯(lián)網(wǎng)發(fā)展的現(xiàn)在,越來越多的網(wǎng)站出現(xiàn),比如個(gè)人博客、單位官網(wǎng)、政務(wù)單位、醫(yī)院機(jī)構(gòu)、金融公司等等,網(wǎng)站所需要展示給用戶看的信息需要被保護(hù),傳輸過程中進(jìn)行加密是非常重要的手段,而廣告的強(qiáng)行植入會(huì)直接影響用戶的訪問體驗(yàn),部分用戶有可能會(huì)誤觸廣告而上當(dāng)受騙。HTTPS的工作原理加入了SSL/TLS協(xié)議,用于對(duì)數(shù)據(jù)傳輸進(jìn)行加密處理,從而防止數(shù)據(jù)被第三方竊取和篡改,對(duì)網(wǎng)站本身和用戶來說,都起到重要的作用。

          見的https網(wǎng)站做的是服務(wù)端認(rèn)證(server authentication),瀏覽器通過證書判斷你所訪問的https://baidu.com是否真的是百度,而不是其他人偽造的網(wǎng)站。同時(shí)還對(duì)流量加密,防止別人竊聽你的流量。

          tls還可以做客戶端認(rèn)證(client authentication),即服務(wù)端判斷客戶端是否為其所信任的客戶端。由此可見,客戶端認(rèn)證用于那些需要受控訪問服務(wù)端。

          在數(shù)據(jù)中心中,有些服務(wù)是非常敏感的,那么我們要做到:

          1. 客戶端和我的流量是加密的,防止別人監(jiān)聽
          2. 客戶端能夠確認(rèn)所訪問的服務(wù)端的確是我們提供的服務(wù)端,而不是別人偽造的服務(wù)端
          3. 只有我信任的客戶端可以訪問我,防止惡意請(qǐng)求

          所以很明顯,前兩個(gè)問題可以通過服務(wù)端認(rèn)證解決,最后一個(gè)問題可以通過客戶端認(rèn)證解決。順便一提,如果要使用客戶端認(rèn)證就必須使用服務(wù)端認(rèn)證。

          先來講講概念然后舉個(gè)tomcat的例子講講怎么做。

          概念

          服務(wù)端認(rèn)證

          不論是做Server authentication還是Client authentication都需要證書。證書的來源有兩種:

          • 由權(quán)威CA簽發(fā),一般都是去購買。也可以使用let's encrypt申請(qǐng)免費(fèi)證書。
          • 自己簽發(fā)

          在一切可能的情況下都應(yīng)該使用權(quán)威CA簽發(fā)的證書,為什么這么建議?因?yàn)檫@里牽涉到一個(gè)信任問題,瀏覽器、編程語言SDK和某些工具都維護(hù)了一個(gè)信任CA證書清單,只要是由這些CA簽發(fā)的證書那就信任,否則就不信任。而這個(gè)鏈條是可以多級(jí)的,這里就不展開了。你只需要知道由信任CA簽發(fā)的所有證書都是可信的。比如JDK自帶的信任CA證書可以通過下面命令看到:

          keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts
          verisignclass2g2ca [jdk], 2016-8-25, trustedCertEntry,
          證書指紋 (SHA1): B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D
          digicertassuredidg3 [jdk], 2016-8-25, trustedCertEntry,
          證書指紋 (SHA1): F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89
          verisignuniversalrootca [jdk], 2016-8-25, trustedCertEntry,
          ...
          

          讓你輸密碼的時(shí)候輸入changeit。

          如果這個(gè)證書不是由信任CA簽發(fā)的(比如自己簽發(fā))會(huì)發(fā)生什么?瀏覽器、編程語言SDK、你所使用的工具會(huì)報(bào)告以下錯(cuò)誤:

          curl:

          curl: (60) SSL certificate problem: self signed certificate in certificate chain
          

          Java:

          Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
           at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
           at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
           at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
           at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
           at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
          ...
          

          瀏覽器:

          這個(gè)錯(cuò)誤實(shí)際上就是在告訴你這個(gè)證書不可信任,可能是一個(gè)偽造站點(diǎn),讓你小心點(diǎn)兒。如果這個(gè)證書由權(quán)威CA簽發(fā),那么就沒有這個(gè)問題了。但是權(quán)威CA簽發(fā)的證書要求申請(qǐng)人擁有域名,如果你這個(gè)服務(wù)是內(nèi)部使用的沒有域名,那就只能自己簽發(fā)了。那么如何解決上面的問題呢?你得把自己簽發(fā)的證書加入到信任CA證書清單里。

          下圖是權(quán)威CA簽發(fā)證書的示例:

          可以看到客戶端有一個(gè)truststore,這個(gè)就是存放信任CA證書的地方,服務(wù)端有一個(gè)keystore,存放的自己的證書及對(duì)應(yīng)的私鑰。

          下圖是自簽發(fā)證書的示例:

          在上面可以看到我們自己成為了一個(gè)Root CA,把它放到客戶端的truststore里。

          客戶端認(rèn)證

          前面講過客戶端認(rèn)證是服務(wù)端來驗(yàn)證客戶端是否可信的機(jī)制,其實(shí)做法和服務(wù)端認(rèn)證類似只不過方向相反。客戶端認(rèn)證大多數(shù)情況下只能是自簽發(fā)的(因?yàn)闆]有域名),雖然不是不可以從權(quán)威CA簽發(fā)但是存在一些問題。下面解釋為什么,假設(shè)權(quán)威CA是let's encrypt,然后服務(wù)端信任它簽發(fā)的所有證書。但是let's encrypt是阿貓阿狗都可以申請(qǐng)的,現(xiàn)在有一個(gè)黑客申請(qǐng)了這個(gè)證書,然后請(qǐng)求你的服務(wù)端,服務(wù)端就認(rèn)可了。

          上面這個(gè)問題可以用這個(gè)方法解決:比如你用let's encrypt申請(qǐng)了A證書,黑客用let's encrypt申請(qǐng)了B證書,你的服務(wù)端的truststore只信任A證書,那么黑客用B證書訪問你的時(shí)候就會(huì)被拒絕。但是這就帶來另一個(gè)問題,比如你在開發(fā)的時(shí)候客戶端證書有這么幾套:生產(chǎn)用、調(diào)試用、開發(fā)用,那么每次客戶端簽發(fā)一個(gè)證書都要更新到你的服務(wù)器的truststore里,這也太麻煩了。

          所以結(jié)合安全性和便利性,我們把自己變成Root CA,然后服務(wù)端信任它,這樣一來服務(wù)端就可以在開發(fā)的時(shí)候把Client Root CA內(nèi)置進(jìn)去,大大減輕了維護(hù)truststore的工作量,看下圖:

          用Tomcat舉個(gè)例子

          下面舉一個(gè)Tomcat做客戶端認(rèn)證的例子,因?yàn)槭菧y(cè)試用,所以服務(wù)端認(rèn)證也是用的自簽發(fā)證書。

          我們用了cfssl這個(gè)工具來生成證書。

          服務(wù)端

          先弄一套目錄:

          # 放自簽發(fā)的服務(wù)端CA根證書
          server-secrets/ca
          # 放自簽發(fā)的服務(wù)端的證書
          server-secrets/cert
          # 放服務(wù)端的keystore和truststore
          server-secrets/jks
          

          生成自簽名CA證書

          新建文件:server-secrets/ca/server-root-ca-csr.json

          內(nèi)容如下:

          {
           "key": {
           "algo": "rsa",
           "size": 2048
           },
           "names": [
           {
           "O": "Company",
           "OU": "Datacenter",
           "L": "Shanghai",
           "ST": "Shanghai",
           "C": "CN"
           }
           ],
           "CN": "server-root-ca"
          }
          

          運(yùn)行下面命令生成Server ROOT CA證書:

          cfssl gencert --initca=true ./server-root-ca-csr.json | cfssljson --bare server-root-ca
          

          會(huì)得到下面幾個(gè)文件:

          server-secrets/ca/
          ├── server-root-ca-key.pem
          ├── server-root-ca.csr
          └── server-root-ca.pem
          

          用下面命令驗(yàn)證證書:

          openssl x509 -in ./server-root-ca.pem -text -noout
          Certificate:
           Data:
           Version: 3 (0x2)
           Serial Number:
           0c:8a:1a:ca:da:fa:4c:17:6c:1f:42:40:4c:f1:90:f4:fd:1d:fe:58
           Signature Algorithm: sha256WithRSAEncryption
           Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca
           Validity
           Not Before: Mar 27 05:14:00 2019 GMT
           Not After : Mar 25 05:14:00 2024 GMT
           Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca
          

          可以看到簽發(fā)人和被簽發(fā)人是同一個(gè)。

          生成自簽發(fā)證書

          新建文件 server-secrets/cert/server-gencert.json,內(nèi)容如下:

          {
           "signing": {
           "default": {
           "usages": [
           "signing",
           "key encipherment",
           "server auth"
           ],
           "expiry": "87600h"
           }
           }
          }
          

          可以看到我們會(huì)生成用來做server auth的證書。

          新建文件 server-secrets/cert/demo-csr.json,內(nèi)容如下:

          {
           "key": {
           "algo": "rsa",
           "size": 2048
           },
           "names": [
           {
           "O": "Company",
           "OU": "Datacenter",
           "L": "Shanghai",
           "ST": "Shanghai",
           "C": "CN"
           }
           ],
           "CN": "server-demo",
           "hosts": [
           "127.0.0.1",
           "localhost"
           ]
          }
          

          看上面的hosts,你可以根據(jù)自己的需要填寫域名或IP,這里因?yàn)槭潜镜匮菔舅允?27.0.0.1和localhost。

          運(yùn)行下面命令生成證書

          cfssl gencert \
           --ca ../ca/server-root-ca.pem \
           --ca-key ../ca/server-root-ca-key.pem \
           --config ./server-gencert.json \
           ./demo-csr.json | cfssljson --bare ./demo
          

          得到文件:

          server-secrets/cert/
          ├── demo-key.pem
          ├── demo.csr
          └── demo.pem
          

          驗(yàn)證結(jié)果:

          openssl x509 -in ./demo.pem -text -noout
          Certificate:
           Data:
           Version: 3 (0x2)
           Serial Number:
           1d:d0:51:97:6c:ce:ea:29:2a:f4:3b:3c:48:a3:69:b0:ef:f3:26:7b
           Signature Algorithm: sha256WithRSAEncryption
           Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-root-ca
           Validity
           Not Before: Mar 27 05:17:00 2019 GMT
           Not After : Mar 24 05:17:00 2029 GMT
           Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=server-demo
          

          可以看到簽發(fā)者是server-root-ca,Subject是server-demo。

          將證書導(dǎo)入keystore

          到 server-secrets/jks,執(zhí)行下面命令生成pkcs12格式的keystore(JDK識(shí)別這個(gè)格式)

          openssl pkcs12 -export \
           -in ../cert/demo.pem \
           -inkey ../cert/demo-key.pem \
           -out server-demo.keystore \
           -name server-demo \
           -CAfile ../ca/server-root-ca.pem \
           -caname root -chain
          

          過程中會(huì)讓你輸入密碼,你就輸入:server-demo-ks。

          得到文件:

          server-secrets/jks/
          └── server-demo.keystore
          

          用JDK提供的keytool看看里面的內(nèi)容:

          keytool -list -keystore server-demo.keystore
          server-demo, 2019-3-27, PrivateKeyEntry,
          證書指紋 (SHA1): B2:E5:46:63:BB:00:E7:82:48:A4:2F:EC:01:41:CE:B4:4B:CE:68:7A
          

          讓你輸入密碼的時(shí)候就輸入:server-demo-ks。

          客戶端

          先弄一套目錄:

          # 放自簽發(fā)的客戶端CA根證書
          client-secrets/ca
          # 放自簽發(fā)的客戶端的證書
          client-secrets/cert
          # 放客戶端的keystore和truststore
          client-secrets/jks
          

          生成自簽名CA證書

          新建文件 client-secrets/ca/client-root-ca-csr.json:

          {
           "key": {
           "algo": "rsa",
           "size": 2048
           },
           "names": [
           {
           "O": "Company",
           "OU": "Datacenter",
           "L": "Shanghai",
           "ST": "Shanghai",
           "C": "CN"
           }
           ],
           "CN": "client-root-ca"
          }
          

          運(yùn)行下面命令生成Client ROOT CA證書:

          cfssl gencert --initca=true ./client-root-ca-csr.json | cfssljson --bare client-root-ca
          

          會(huì)得到下面幾個(gè)文件:

          client-secrets/ca/
          ├── client-root-ca-key.pem
          ├── client-root-ca.csr
          └── client-root-ca.pem
          

          用下面命令驗(yàn)證證書:

          openssl x509 -in ./client-root-ca.pem -text -noout
          Certificate:
           Data:
           Version: 3 (0x2)
           Serial Number:
           7e:fc:f3:53:07:1a:17:ae:24:34:d5:1d:00:02:d6:e4:24:09:92:12
           Signature Algorithm: sha256WithRSAEncryption
           Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca
           Validity
           Not Before: Mar 27 05:20:00 2019 GMT
           Not After : Mar 25 05:20:00 2024 GMT
           Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca
          

          可以看到簽發(fā)人和被簽發(fā)人是同一個(gè)。

          生成自簽發(fā)證書

          新建文件 client-secrets/cert/client-gencert.json,內(nèi)容如下:

          {
           "signing": {
           "default": {
           "usages": [
           "signing",
           "key encipherment",
           "client auth"
           ],
           "expiry": "87600h"
           }
           }
          }
          

          可以看到我們會(huì)生成用來做client auth的證書。

          新建文件 client-secrets/cert/demo-csr.json,內(nèi)容如下:

          {
           "key": {
           "algo": "rsa",
           "size": 2048
           },
           "names": [
           {
           "O": "Company",
           "OU": "Datacenter",
           "L": "Shanghai",
           "ST": "Shanghai",
           "C": "CN"
           }
           ],
           "CN": "client-demo"
          }
          

          這里沒有hosts,這是因?yàn)槲覀儾恍枰眠@個(gè)證書來做服務(wù)端認(rèn)證。

          運(yùn)行下面命令生成證書

          cfssl gencert \
           --ca ../ca/client-root-ca.pem \
           --ca-key ../ca/client-root-ca-key.pem \
           --config ./client-gencert.json \
           ./demo-csr.json | cfssljson --bare ./demo
          

          得到文件:

          client-secrets/cert/
          ├── demo-key.pem
          ├── demo.csr
          └── demo.pem
          

          驗(yàn)證結(jié)果:

          openssl x509 -in ./demo.pem -text -noout
          Certificate:
           Data:
           Version: 3 (0x2)
           Serial Number:
           6e:50:e2:2c:02:bb:ef:fd:03:d9:2c:0a:8f:ba:90:65:fb:c4:b5:75
           Signature Algorithm: sha256WithRSAEncryption
           Issuer: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-root-ca
           Validity
           Not Before: Mar 27 05:21:00 2019 GMT
           Not After : Mar 24 05:21:00 2029 GMT
           Subject: C=CN, ST=Shanghai, L=Shanghai, O=Company, OU=Datacenter, CN=client-demo
          

          可以看到簽發(fā)者是client-root-ca,Subject是client-demo。

          將證書導(dǎo)入keystore

          到 client-secrets/jks,執(zhí)行下面命令生成pkcs12格式的keystore(JDK識(shí)別這個(gè)格式)

          openssl pkcs12 -export \
           -in ../cert/demo.pem \
           -inkey ../cert/demo-key.pem \
           -out client-demo.keystore \
           -name client-demo \
           -CAfile ../ca/client-root-ca.pem \
           -caname root -chain
          

          過程中會(huì)讓你輸入密碼,你就輸入:client-demo-ks。

          得到文件:

          client-secrets/jks/
          └── client-demo.keystore
          

          用JDK提供的keytool看看里面的內(nèi)容:

          keytool -list -keystore client-demo.keystore
          client-demo, 2019-3-27, PrivateKeyEntry,
          證書指紋 (SHA1): 83:AE:0E:5E:0C:CE:86:C9:D1:84:D7:6F:87:F3:76:1F:B4:3E:46:31
          

          讓你輸入密碼的時(shí)候就輸入:client-demo-ks。

          兩端互信

          好了,到此為止server和client的證書都已經(jīng)生成了,接下來只需要將各自的root-ca添加到彼此都truststore中。

          把server-root-ca導(dǎo)入到client的truststore中

          cd client-secrets/jks
          keytool -importcert \
           -alias server-root-ca \
           -storetype pkcs12 \
           -keystore client.truststore \
           -storepass client-ts \
           -file ../../server-secrets/ca/server-root-ca.pem -noprompt
          

          注意上面的-storepass參數(shù),這個(gè)是trustore的密碼:client-ts。

          得到文件:

          client-secrets/jks/
          └── client.truststore
          

          用JDK提供的keytool看看里面的內(nèi)容:

          keytool -list -keystore client.truststore
          server-root-ca, 2019-3-27, trustedCertEntry,
          證書指紋 (SHA1): 75:E3:78:97:85:B2:29:38:25:3C:FD:EC:68:97:9B:78:A0:5F:BB:9D
          

          讓你輸入密碼的時(shí)候就輸入:client-ts。

          把client-root-ca導(dǎo)入到server的truststore中

          cd server-secrets/jks
          keytool -importcert \
           -alias client-root-ca \
           -storetype pkcs12 \
           -keystore server.truststore \
           -storepass server-ts \
           -file ../../client-secrets/ca/client-root-ca.pem -noprompt
          

          注意上面的-storepass參數(shù),這個(gè)是trustore的密碼:server-ts。

          得到文件:

          server-secrets/jks/
          └── server.truststore
          

          用JDK提供的keytool看看里面的內(nèi)容:

          keytool -list -keystore server.truststore
          client-root-ca, 2019-3-27, trustedCertEntry,
          證書指紋 (SHA1): 1E:95:2C:12:AA:7E:6D:E7:74:F1:83:C2:B8:73:6F:EE:57:FB:CA:46
          

          讓你輸入密碼的時(shí)候就輸入:server-ts。

          配置Tomcat

          好了,我們現(xiàn)在client和server都有了自己證書放在了自己的keystore中,而且把彼此的root-ca證書放到了自己的truststore里。現(xiàn)在我們弄一個(gè)tomcat作為server,然后為他配置SSL。

          修改tomcat/conf/server.xml,添加如下Connector:

          <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
           <SSLHostConfig
           certificateVerification="required"
           truststoreFile="/path/to/server-secrets/jks/server.truststore"
           truststorePassword="server-ts" 
           truststoreType="PKCS12">
           <Certificate
           certificateKeyAlias="server-demo"
           certificateKeystoreFile="/path/to/server-secrets/demo-jks/server-demo.keystore"
           certificateKeystoreType="PKCS12"
           certificateKeystorePassword="server-demo-ks"
           type="RSA" />
           </SSLHostConfig>
          </Connector>
          

          可以看到我們開啟了客戶端認(rèn)證certificateVerification="required",也開啟了服務(wù)端認(rèn)證<Certificate>。記得修改上面的keystore和truststore的路徑。

          修改tomcat/conf/web.xml,添加如下元素:

          <security-constraint>
           <web-resource-collection>
           <web-resource-name>Automatic Forward to HTTPS/SSL</web-resource-name>
           <url-pattern>/*</url-pattern>
           </web-resource-collection>
           <user-data-constraint>
           <transport-guarantee>CONFIDENTIAL</transport-guarantee>
           </user-data-constraint>
          </security-constraint>
          

          這個(gè)作用是當(dāng)訪問8080端口時(shí),都跳轉(zhuǎn)到8443端口,強(qiáng)制走HTTPS。

          啟動(dòng)tomcat:

          tomcat/bin/catalina.sh run
          

          用curl測(cè)試

          好了,我們現(xiàn)在用curl來測(cè)試訪問一下:

          curl https://localhost:8443/
          curl: (60) SSL certificate problem: self signed certificate in certificate chain
          ...
          

          看到curl說服務(wù)端用的是一個(gè)自簽發(fā)的證書,不可信,也就是說服務(wù)端認(rèn)證失敗。添加--insecure試試:

          curl --insecure https://localhost:8443/
          curl: (35) error:1401E412:SSL routines:CONNECT_CR_FINISHED:sslv3 alert bad certificate
          

          這里就說明客戶端認(rèn)證失敗。

          所以如果要正確訪問得像下面這樣,指定server-root-ca證書,以及客戶端自己簽發(fā)的證書及private key:

          curl --cacert server-secrets/ca/server-root-ca.pem \
           --key client-secrets/cert/demo-key.pem \
           --cert client-secrets/cert/demo.pem \
           https://localhost:8443/
          <!DOCTYPE html>
          <html lang="en">
          ...
          

          Httpclient測(cè)試

          我們現(xiàn)在用Httpclient來訪問看看。pom.xml中添加依賴:

          <dependency>
           <groupId>org.apache.httpcomponents</groupId>
           <artifactId>httpclient</artifactId>
           <version>4.5.7</version>
          </dependency>
          

          Java代碼,記得把文件路徑改掉:

          import org.apache.http.HttpEntity;
          import org.apache.http.HttpException;
          import org.apache.http.client.methods.CloseableHttpResponse;
          import org.apache.http.client.methods.HttpGet;
          import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
          import org.apache.http.impl.client.CloseableHttpClient;
          import org.apache.http.impl.client.HttpClients;
          import org.apache.http.ssl.SSLContexts;
          import org.apache.http.util.EntityUtils;
          import javax.net.ssl.SSLContext;
          import java.io.File;
          import java.io.IOException;
          public class Client {
           public static void main(String[] args) throws Exception {
           SSLContext sslcontext=SSLContexts.custom()
           .loadTrustMaterial(
           new File("/path/to/client-secrets/demo-jks/client.truststore"),
           "client-ts".toCharArray()
           )
           .loadKeyMaterial(
           new File("/path/to/client-secrets/demo-jks/client-demo.keystore"),
           "client-demo-ks".toCharArray(),
           "client-demo-ks".toCharArray())
           .build();
           SSLConnectionSocketFactory sslsf=new SSLConnectionSocketFactory(
           sslcontext,
           SSLConnectionSocketFactory.getDefaultHostnameVerifier());
           CloseableHttpClient httpclient=HttpClients.custom()
           .setSSLSocketFactory(sslsf)
           .build();
           HttpGet httpGet=new HttpGet("https://localhost:8443");
           CloseableHttpResponse response=httpclient.execute(httpGet);
           try {
           System.out.println(response.getStatusLine());
           HttpEntity entity=response.getEntity();
           System.out.println(EntityUtils.toString(entity));
           } finally {
           response.close();
           }
           }
          }
          

          安全性考慮

          • 所有private key都很重要!如果它被泄漏了,就要回收它所對(duì)應(yīng)都證書。如果CA的private key泄漏了,那么用它簽發(fā)的所有證書都要被回收。
          • keystore和truststore的密碼設(shè)置的要復(fù)雜一些。

          關(guān)于反向代理

          因?yàn)榉?wù)端認(rèn)證所需要的證書直接配置在Tomcat上的,因此在做反向代理的時(shí)候不能使用SSL Termination模式,而是得使用SSL Passthrough模式。

          其他語言、SDK、工具

          上面講的方法不是只適用于Tomcat和Httpclient的,TLS的服務(wù)端認(rèn)證與客戶端認(rèn)證應(yīng)該在絕大部分的語言、SDK、類庫都有支持,請(qǐng)自行參閱文檔實(shí)踐。文中的keystore和truststore是Java特有的,不過不必迷惑,因?yàn)樗鼈儍H僅起到一個(gè)存放證書和private key的保險(xiǎn)箱,有些語言或工具則是直接使用證書和private key,比如前面提到的curl。

          歡迎工作一到五年的Java工程師朋友們加入Java程序員開發(fā): 721575865

          群內(nèi)提供免費(fèi)的Java架構(gòu)學(xué)習(xí)資料(里面有高可用、高并發(fā)、高性能及分布式、Jvm性能調(diào)優(yōu)、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個(gè)知識(shí)點(diǎn)的架構(gòu)資料)合理利用自己每一分每一秒的時(shí)間來學(xué)習(xí)提升自己,不要再用"沒有時(shí)間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個(gè)交代!

          最近寫小程序,但是小程序的接口得通過https的形式訪問,所以用nginx轉(zhuǎn)發(fā)了一下。想到Google搜索引擎會(huì)提高h(yuǎn)ttps網(wǎng)站的權(quán)重,索性把我的網(wǎng)站改造成同時(shí)支持http和https了。看效果

          http形式訪問


          https形式訪問


          我是用LET’S ENCRYPT來生成證書的,這個(gè)應(yīng)該是用的最多的一個(gè)工具,也很方便。

          我直接參考了官方文檔上關(guān)于在CentOS 7上用nginx來讓網(wǎng)站支持https的教程
          https://certbot.eff.org/lets-encrypt/centosrhel7-nginx

          1.下載

          sudo yum install certbot python2-certbot-nginx

          2.執(zhí)行命令
          默認(rèn)修改/usr/local/nginx/conf目錄下的nginx.conf文件

          certbot --nginx -d www.erlie.cc

          如果不在這個(gè)目錄可以用–nginx-server-root這個(gè)參數(shù)來指定

          certbot --nginx --nginx-server-root=/yourpath -d www.erlie.cc	

          如果要為多個(gè)域名生成的話

          -d 域名1 -d 域名2

          或者每次指定一個(gè),執(zhí)行多次
          過程中會(huì)有2個(gè)選項(xiàng)1和2

          如果選 1,則通過 HTTP 和 HTTPS 都可以訪問。
          如果選 2,則所有通過 HTTP 來的請(qǐng)求,都會(huì)被 301 重定向到 HTTPS

          中途中可能會(huì)遇到各種環(huán)境問題,Google解決即可。

          我說一個(gè)我遇到的坑,我原來編譯的時(shí)候沒有選擇SSL module,所以我得重新編譯一下,編譯完成之后我是用如下命令重啟的

          nginx -s reload

          結(jié)果https訪問一直有問題,后來我才意識(shí)到。sbin目錄下重新生成的nginx得重啟才能生效。
          nginx -s reload只是熱部署配置文件,二進(jìn)制文件nginx并不生效

          此時(shí)http://www.erlie.cc和https://www.erlie.cc就都可以訪問了

          nginx.conf配置

          server {
          	listen       80;
          	server_name  www.erlie.cc;
          
          	#charset koi8-r;
          
          	access_log  /usr/local/nginx/logs/access.log combined;
          
          	location=/ {
          		root   /product/new-blog-fe/dist/view;
          		index  index.html;
          	}
          
          
          	location ~ .*\.html$ {
          		root   /product/new-blog-fe/dist/view;
          		index  index.html;
          	}
          
          
          	location / {
          		proxy_pass  http://127.0.0.1:8080/;
             }
             
          
             location ~ .*\.(gif|jpeg|png|bmp|swf|flv|ico)$ {
          		root   /product/new-blog-fe;
          		if (-f $request_filename) {
          		  expires 1d;
          		  break;
          	   }
             }
          
             location ~ .*\.(js|css)?$ {
          		root   /product/new-blog-fe;
          		if (-f $request_filename) {
          		  expires 1d;
          		  break;
          	   }
             }
          
          
          	#error_page  404              /404.html;
          
          	# redirect server error pages to the static page /50x.html
          	#
          	error_page   500 502 503 504  /50x.html;
          	location=/50x.html {
          		root   html;
          	}
          
          	listen 443 ssl; # managed by Certbot
          	ssl_certificate /etc/letsencrypt/live/www.erlie.cc/fullchain.pem; # managed by Certbot
          	ssl_certificate_key /etc/letsencrypt/live/www.erlie.cc/privkey.pem; # managed by Certbot
          	include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
          	ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
          }
          123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657

          最后面的5行就是前面的命令自動(dòng)幫你生成的,非常方便,都不用自己配置。
          可以看到我把接口的請(qǐng)求都轉(zhuǎn)發(fā)到本地http://127.0.0.1:8080/,你應(yīng)該猜到了這是一個(gè)Spring Boot項(xiàng)目

          前端怎么寫?

          為了讓前端在訪客通過http方式訪問的時(shí)候調(diào)用http接口。通過https訪問的時(shí)候調(diào)用https接口,我是這樣做的

          nb.js

          var conf={
              serverHot : window.location.origin
          };
          var _nb={
              request: function (param) {
                  var _this=this;
                  $.ajax({
                      type       : param.method || 'get',
                      url        : param.url || '',
                      dataType   : param.type || 'json',
                      data       : param.data || '',
                      xhrFields  : {withCredentials: true},
                      crossDomain: true,
                      contentType: param.contentType || 'application/x-www-form-urlencoded;charset=UTF-8',
                      success: function (res) {
                      	typeof param.success==='function' && param.success(res.data, res.msg);
                      },
                      error: function (err) {
                      	typeof param.error==='function' && param.error(err.statusText);
                      }
          
                  })
              },
              // 獲取服務(wù)器地址
              getServerUrl : function(path) {
                  return conf.serverHot + path;
              }
          }
          
          module.exports=_nb;
          123456789101112131415161718192021222324252627282930

          window.location.origin為拿到https://www.erlie.cc類似這樣的請(qǐng)求地址,可以在瀏覽器自己試一下


          user-service.js請(qǐng)求用戶相關(guān)的接口

          var _nb=require('util/nb.js');
          
          var _user={
              // 用戶登錄
              login : function(userInfo, resolve, reject){
                  _nb.request({
                      url     : _nb.getServerUrl('/user/login'),
                      data    : userInfo,
                      method  : 'POST',
                      success : resolve,
                      error   : reject
                  });
              }
          }
          module.exports=_user;
          123456789101112131415

          userInfo為請(qǐng)求參數(shù)
          resolve為調(diào)用成功后執(zhí)行的函數(shù)
          reject為調(diào)用失敗后執(zhí)行的函數(shù)

          自動(dòng)續(xù)期

          Let’s Encrypt 的證書90天就過期了,所以,你還要設(shè)置上自動(dòng)化的更新腳本,最容易的莫過于使用 crontab 了。使用 crontab -e 命令加入如下的定時(shí)作業(yè)(每個(gè)月都強(qiáng)制更新一下)輸入

          0 0 * * * certbot renew

          鑒于很多人問我要付費(fèi)專欄pdf版本,因?yàn)閷诓荒茉陔娔X閱讀,索性直接開源了,希望能幫助到各位小伙伴

          免費(fèi)領(lǐng)取

          免費(fèi)領(lǐng)取

          免費(fèi)領(lǐng)取

          重要的事情說三遍。點(diǎn)擊我的頭像私信專欄即可


          主站蜘蛛池模板: 97久久精品无码一区二区天美| 玩弄放荡人妻一区二区三区| 性盈盈影院免费视频观看在线一区| 亚洲国产精品一区二区九九| 国产微拍精品一区二区| 超清无码一区二区三区| 日本一区免费电影| 夜精品a一区二区三区| 99精品国产高清一区二区麻豆| 国产精品视频一区二区三区四| 99久久精品费精品国产一区二区| 福利电影一区二区| 人妻夜夜爽天天爽一区| 日韩在线视频一区| 国产一区二区免费在线| 正在播放国产一区| 老湿机一区午夜精品免费福利| 国产精品538一区二区在线| 怡红院美国分院一区二区| 在线观看一区二区三区视频| 国产精品日韩一区二区三区| 日韩一区二区三区在线 | 国产午夜毛片一区二区三区| 一区二区在线视频免费观看| 精品成人av一区二区三区| 亚洲综合av永久无码精品一区二区| 中文字幕久久亚洲一区| 中文字幕在线精品视频入口一区| 国产美女露脸口爆吞精一区二区 | 国产一区二区不卡老阿姨| 国产一区二区在线视频| 在线观看国产一区| 国产一区二区视频在线播放| 一区二区三区在线免费| 色一情一乱一伦一区二区三区日本| 国产福利无码一区在线| 欧美亚洲精品一区二区| 99国产精品欧美一区二区三区 | 91精品福利一区二区| 亚洲国产视频一区| 国产韩国精品一区二区三区久久|