自已公司内部的系统,需要修改为https访问,使用nginx+tomcat,此文记录了整个过程,因为系统使用了jsp,而且页面中大量使用了request.getscheme()+“: //”+request.getservername()+“:”+request.getserverport()来组合url进行数据的提交,导致最终界面中出现了http://协议,为了不改动代码,最终方案采用nginx和tomcat都开启https,由nginx转发到tomcat的https上,最终完美搭建成功。
一、获取证书
如果是互联网应用,需要向权威机构申请证书,
此处给出局域网生成私有证书的方法(在linux下执行):
1.创建服务器证书密钥文件 server.key:
openssl genrsa -des3 -out server.key 1024
输入密码,确认密码,自己随便定义,但是要记住,后面会用到。
2.创建服务器证书的申请文件 server.csr
openssl req -new -key server.key -out server.csr
输出内容为:
enter pass phrase for root.key: ← 输入前面创建的密码 country name (2 letter code) [au]:cn ← 国家代号,中国输入cn state or province name (full name) [some-state]:henan ← 省的全名,拼音 locality name (eg, city) []:zhengzhou ← 市的全名,拼音 organization name (eg, company) [internet widgits pty ltd]:mycompany. ← 公司英文名 organizational unit name (eg, section) []: ← 可以不输入 common name (eg, your name) []: ← 此时不输入 email address []:admin@mycompany.com ← 电子邮箱,可随意填 please enter the following ‘extra' attributes to be sent with your certificate request a challenge password []: ← 可以不输入 an optional company name []: ← 可以不输入
3.备份一份服务器密钥文件
cp server.key server.key.org
4.去除文件口令,生成私钥
openssl rsa -in server.key.org -out server.key
5.生成证书文件server.crt(公钥,会发送给浏览器)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
6.有用的就是server.key和server.crt文件,下面配置nginx时会用到
二、配置nginx
修改conf/nginx.conf文件,修改server段的端口监听部分
server { #listen 80; #比起默认的80 使用了443 默认 是ssl方式 listen 443 default ssl; #开启 如果把ssl on;这行去掉,ssl写在443端口后面。这样http和https的链接都可以用 ssl on; #证书(公钥.发送到客户端的) ssl_certificate ssl/server.crt; #私钥 ssl_certificate_key ssl/server.key;
修改反向代理的部分
location / { proxy_pass https://127.0.0.1:8443; proxy_redirect off; proxy_set_header host $host:$server_port; proxy_set_header remote_addr $remote_addr; 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; add_header content-security-policy upgrade-insecure-requests; index index.html index.htm index.jsp; }
将http请求重写为https请求的配置(写在server段内)
error_page 497 https://$host:$server_port$uri;
三、配置tomcat,打开https请求
修改conf/server.xml文件,打开https的配置段,配置证书路径,同时将server.crt和server.key文件拷贝至tomcat/ssl目录下
<connector port="8443" protocol="org.apache.coyote.http11.http11nioprotocol" maxthreads="150" sslenabled="true" scheme="https"> <sslhostconfig> <certificate certificatefile="ssl/server.crt" certificatekeyfile="ssl/server.key" type="rsa" /> </sslhostconfig> </connector>
四、各类问题解决
1、将访问https端口的http请求地址重写为https协议
在nginx.conf文件内的server段中,增加对497状态码的转发配置
error_page 497 https://$host:$server_port$uri;
原理:当站点只允许https访问时,使用http访问时会报出497错误码,此时使用error_page指令将497代码的url重定向到https的正确路径
http code 497的官方解释:
497 - normal request was sent to https
2、redirect转发时丢失端口号的处理
网上查到的各种配置中,很多配置中对host的设置使用了h o s t 变量,因为 host变量,因为host变量,因为host中不含端口号信息,所以会丢失端口号,解决办法为修改h o s t 为 host为host为http_post或h o s t : host:host:server_port
proxy_set_header host $host:$server_port; #这两种配置都可以,其中$http_post是$http_header的匹配规则,取的是请求头中host的属性值 proxy_set_header host $http_host;
3、jsp中使用request.getscheme()只得到http问题处理
这个问题目前只找到了一种解决方案,就是将tomcat也开启https协议,nginx转发时使用https://协议进行转发,就能完美解决这个问题。
附表 nginx.conf中可以使用的变量
变量名 | 定义 |
---|---|
$arg_parameter | get请求中变量名parameter参数的值 |
$args | 这个变量等于get请求中的参数。例如,foo=123&bar=blahblah;这个变量只可以被修改 |
$binary_remote_addr | 二进制码形式的客户端地址。 |
$body_bytes_sent | 传送页面的字节数 |
$content_length | 请求头中的content-length字段。 |
$content_type | 请求头中的content-type字段。 |
$cookie_cookie | cookie cookie的值。 |
$document_root | 当前请求在root指令中指定的值。 |
$document_uri | 与$uri相同。 |
$host | 请求中的主机头(host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写,不包含端口。 |
$hostname | 机器名使用 gethostname系统调用的值 |
$http_header | http请求头中的内容,header为http请求中的内容转为小写,-变为_(破折号变为下划线),例如:$http_user_agent(uaer-agent的值); |
$sent_http_header | http响应头中的内容,header为http响应中的内容转为小写,-变为_(破折号变为下划线),例如: $sent_http_cache_control, $sent_http_content_type…; |
$is_args | 如果$args设置,值为"?“,否则为”"。 |
$limit_rate | 这个变量可以限制连接速率。 |
$nginx_version | 当前运行的nginx版本号。 |
$query_string | 与$args相同。 |
$remote_addr | 客户端的ip地址。 |
$remote_port | 客户端的端口。 |
$remote_user | 已经经过auth basic module验证的用户名。 |
$request_filename | 当前连接请求的文件路径,由root或alias指令与uri请求生成。 |
$request_body | 这个变量(0.7.58+)包含请求的主要信息。在使用proxy_pass或fastcgi_pass指令的location中比较有意义。 |
$request_body_file | 客户端请求主体信息的临时文件名。 |
$request_completion | 如果请求成功,设为"ok";如果请求未完成或者不是一系列请求中最后一部分则设为空。 |
$request_method | 这个变量是客户端请求的动作,通常为get或post。包括0.8.20及之前的版本中,这个变量总为main request中的动作,如果当前请求是一个子请求,并不使用这个当前请求的动作。 |
$request_uri | 这个变量等于包含一些客户端请求参数的原始uri,它无法修改,请查看$uri更改或重写uri。 |
$scheme | 所用的协议,比如http或者是https,比如rewrite ^(.+)$ $scheme://example.com$1 redirect; |
$server_addr | 服务器地址,在完成一次系统调用后可以确定这个值,如果要绕开系统调用,则必须在listen中指定地址并且使用bind参数。 |
$server_name | 服务器名称。 |
$server_port | 请求到达服务器的端口号。 |
$server_protocol | 请求使用的协议,通常是http/1.0或http/1.1。 |
$uri | 请求中的当前uri(不带请求参数,参数位于args,不同于浏览器传递的args),不同于浏览器传递的request_uri的值,它可以通过内部重定向,或者使用index指令进行修改。不包括协议和主机名,例如/foo/bar.html |
到此这篇关于nginx+tomcat配置https的实现的文章就介绍到这了,更多相关nginx+tomcat配置https内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论