目前主流的網站都要求 HTTPS 安全訪問,Google Chrome 瀏覽器、微信內置瀏覽器打開非 HTTPS 的網頁,都會提示不安全。若是作微信端開發,也是必需要 HTTPS 的網址才能夠,可見 HTTPS 愈來愈重要了。javascript
還不瞭解什麼是 Oracle APEX,請閱讀個人另外一篇文章:Oracle APEX 系列文章1:Oracle APEX, 讓你秒變全棧開發的黑科技css
若是你按照鋼哥以前的文章已經搭建好了 Oracle APEX 環境,那麼你的應用架構應該以下圖所示:html
這裏簡單回顧一下各部分組件的做用:java
80
) 端口和 HTTPS (443
) 端口,若是請求的是靜態文件(如:image, js 或者 css),則直接獲取/i/
目錄中的內容,對於其餘動態請求(如:APEX請求),進一步轉發至後端 Tomcat 服務器作進一步處理。ORDS
應用;原理比較簡單,而咱們要作的就是在 Nginx 層面講 HTTP 請求轉發到 HTTPS 上,進而實現全站 HTTPS 訪問。nginx
這裏以在阿里雲上購買免費 SSL 證書爲例,首先登陸阿里雲控制檯,進入安全(雲盾)-> SSL證書(應用安全)
,點擊購買證書
。web
進入到選擇購買頁面,提示1年須要五千多大洋,土豪直接點擊付款便可。數據庫
好吧,我是窮人,只能看看有沒有免費證書。實際上是有的,依次點擊Symantec
-> 1個域名
-> 免費型DV SSL
,成功激活30人:)express
接下來回到控制檯,補全剛剛申請的證書信息。apache
按照提示補全信息。
後端
鋼哥提示:因爲咱們申請的是阿里雲的免費證書,只能做用於一個固定域名,通常咱們都不會把主域名用來放置APEX應用,因此這裏能夠填寫諸如:apex.xxx.com 的二級域名。若是你想要免費通配符域名,能夠移步這裏: 使用Let’s Encrypt給網站加上免費HTTPS證書另外須要注意的是,第二步的驗證環節,若是你選擇的是文件驗證,請必定按照提示把對應的驗證文件放到你的服務器上,
正常文件驗證通常不會超過5分鐘
,若是長時間沒驗證經過,必定是你操做有問題了。
當你的證書申請經過後,就能夠點擊下載
連接了。
將 SSL 證書添加進nginx.conf
,按照下載證書
頁面的提示配置 Nginx:
個人nginx.conf
文件內容以下:
worker_processes auto; worker_rlimit_nofile 10000; error_log logs/error.log; events { worker_connections 2048; #==告訴nginx收到一個新連接通知後接受盡量多的連接 multi_accept on; #==設置用於複用客戶端線程的輪訓方法 use epoll; } http { include mime.types; default_type application/octet-stream; charset UTF-8; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /etc/nginx/logs/access_log.log main; server_tokens off; sendfile on; tcp_nopush on; keepalive_timeout 65; proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; #==設置nginx採用gzip壓縮的形式發送數據,減小發送數據量,但會增長請求處理時間及CPU處理時間,須要權衡 gzip on; #==加vary給代理服務器使用,針對有的瀏覽器支持壓縮,有個不支持,根據客戶端的HTTP頭來判斷是否須要壓縮 gzip_vary on; gzip_http_version 1.0; gzip_types text/plain application/javascript application/x-javascript text/css; gzip_min_length 1024; gzip_comp_level 3; server { listen 443 default_server; server_name apex.wangfanggang.com; ssl on; ssl_certificate cert/214412416080589.pem; ssl_certificate_key cert/214412416080589.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location = / { # 默認打開某個APEX應用 rewrite ^/(.*) https://apex.wangfanggang.com/ords/f?p=102 redirect; } location ~* \.(eot|ttf|woff|woff2)$ { add_header Access-Control-Allow-Origin *; } location ^~ /i/ { alias /u01/tomcat/webapps/i/; } location ^~ /ords/ { # 將請求轉發到tomcat上 proxy_pass http://localhost:8080/ords/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 20m; } } server { listen 80 default_server; server_name apex.wangfanggang.com; include /etc/nginx/default.d/*.conf; location = / { # 全部http請求統一重定向到https上 rewrite ^/(.*) https://apex.wangfanggang.com/ords/f?p=102 redirect; } location ~* \.(eot|ttf|woff|woff2)$ { add_header Access-Control-Allow-Origin *; } location ^~ /i/ { alias /u01/tomcat/webapps/i/; } location ^~ /ords/ { # 全部http請求統一重定向到https上 proxy_pass https://apex.wangfanggang.com/ords/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 20m; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } }
配置完 nginx,別忘了重啓令配置生效。再次在瀏覽器中訪問 APEX 頁面,若是能看到以下界面,恭喜你,你的 SSL 證書生效了!!
鋼哥在配置的時候 SSL 證書時遇到了一個奇怪的問題,就是啓用 SSL 證書後,訪問 APEX 頁面時會發生重定向錯誤(302 error:too_many_redirects
),致使沒法正常訪問。
通過跟同事幾天的研究,發現除了要在 Nginx 上啓用 SSL 證書之外,還必須在 Tomcat 上也啓用。仍是回到阿里雲控制檯證書下載頁面,找到 Tomcat 配置證書部分。
鋼哥提示:特別要注意的是,這裏要選擇
JKS
格式證書進行安裝,不然會有問題。
在 Tomcat 的server.xml
文件中添加以下內容:
<Valve className = "org.apache.catalina.valves.RemoteIpValve" remoteIpHeader = "X-Forwarded-For" protocolHeader = "X-Forwarded-Proto" />
個人server.xml
文件內容:
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Note: A "Server" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/server.html --> <Server port="8005" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <!-- Security listener. Documentation at /docs/config/listeners.html <Listener className="org.apache.catalina.security.SecurityListener" /> --> <!-- APR library loader. Documentation at /docs/apr.html --> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <!-- Prevent memory leaks due to use of particular java/javax APIs --> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <!-- Global JNDI resources Documentation at /docs/jndi-resources-howto.html --> <GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource name = "UserDatabase" auth="Container" type = "org.apache.catalina.UserDatabase" description = "User database that can be updated and saved" factory = "org.apache.catalina.users.MemoryUserDatabaseFactory" pathname = "conf/tomcat-users.xml" /> </GlobalNamingResources> <!-- A "Service" is a collection of one or more "Connectors" that share a single "Container" Note: A "Service" is not itself a "Container", so you may not define subcomponents such as "Valves" at this level. Documentation at /docs/config/service.html --> <Service name = "Catalina"> <!-- The connectors can use a shared executor, you can define one or more named thread pools --> <!-- <Executor name = "tomcatThreadPool" namePrefix = "catalina-exec-" maxThreads = "150" minSpareThreads = "4" /> --> <!-- A "Connector" represents an endpoint by which requests are received and responses are returned. Documentation at : Java HTTP Connector: /docs/config/http.html Java AJP Connector: /docs/config/ajp.html APR (HTTP/AJP) Connector: /docs/apr.html Define a non-SSL/TLS HTTP/1.1 Connector on port 8080 --> <Connector port = "8080" protocol = "HTTP/1.1" connectionTimeout = "20000" redirectPort = "8443" /> <!-- A "Connector" using the shared thread pool --> <!-- <Connector executor = "tomcatThreadPool" port="8080" protocol = "HTTP/1.1" connectionTimeout = "20000" redirectPort = "8443" /> --> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 This connector uses the NIO implementation. The default SSLImplementation will depend on the presence of the APR/native library and the useOpenSSL attribute of the AprLifecycleListener. Either JSSE or OpenSSL style configuration may be used regardless of the SSLImplementation selected. JSSE style configuration is used below. --> <!-- <Connector port = "8443" protocol = "org.apache.coyote.http11.Http11NioProtocol" maxThreads = "150" SSLEnabled = "true"> <Certificate certificateKeystoreFile = "conf/localhost-rsa.jks" type = "RSA" /> </Connector> --> <Connector port="8443" protocol = "HTTP/1.1" SSLEnabled = "true" scheme = "https" secure = "true" keystoreFile = "cert/214412416080589.jks" keystorePass = "abc123" clientAuth = "false" SSLProtocol = "TLSv1+TLSv1.1+TLSv1.2" ciphers = "TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256" /> <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2 This connector uses the APR/native implementation which always uses OpenSSL for TLS. Either JSSE or OpenSSL style configuration may be used. OpenSSL style configuration is used below. --> <!-- <Connector port = "8443" protocol = "org.apache.coyote.http11.Http11AprProtocol" maxThreads = "150" SSLEnabled = "true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig> <Certificate certificateKeyFile = "conf/localhost-rsa-key.pem" certificateFile = "conf/localhost-rsa-cert.pem" certificateChainFile = "conf/localhost-rsa-chain.pem" type = "RSA" /> </SSLHostConfig> </Connector> --> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port = "8009" protocol = "AJP/1.3" redirectPort = "8443" /> <!-- An Engine represents the entry point (within Catalina) that processes every request. The Engine implementation for Tomcat stand alone analyzes the HTTP headers included with the request, and passes them on to the appropriate Host (virtual host). Documentation at /docs/config/engine.html --> <!-- You should set jvmRoute to support load-balancing via AJP ie : <Engine name = "Catalina" defaultHost = "localhost" jvmRoute = "jvm1"> --> <Engine name = "Catalina" defaultHost = "localhost"> <!-- For clustering, please take a look at documentation at: /docs/cluster-howto.html (simple how to) /docs/config/cluster.html (reference documentation) --> <!-- <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" /> --> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className = "org.apache.catalina.realm.UserDatabaseRealm" resourceName = "UserDatabase" /> </Realm> <Host name = "localhost" appBase = "webapps" unpackWARs = "true" autoDeploy = "true"> <Valve className = "org.apache.catalina.valves.RemoteIpValve" remoteIpHeader = "X-Forwarded-For" protocolHeader = "X-Forwarded-Proto" /> </Host> </Engine> </Service> </Server>
重啓 Tomcat 服務器,再次訪問 APEX,煩人的重定向問題終於得以解決。
用 HTTPS 協議來安全地訪問你的 APEX 應用,這一點特別是對企業應用特別重要,相信你如今已經掌握瞭如何在 APEX 上全站啓用 SSL 證書。本文若有遺漏或不足的地方也請隨時跟鋼哥交流,讓咱們共同窗習,共同進步!