目前主流的网站都要求 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 证书。本文若有遗漏或不足的地方也请随时跟钢哥交流,让咱们共同窗习,共同进步!