Nginx+Tomcat配置https

自已公司内部的系统,需要修改为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为 hosthttp_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_PARAMETERGET请求中变量名PARAMETER参数的值
$args这个变量等于GET请求中的参数。例如,foo=123&bar=blahblah;这个变量只可以被修改
$binary_remote_addr二进制码形式的客户端地址。
$body_bytes_sent传送页面的字节数
$content_length请求头中的Content-length字段。
$content_type请求头中的Content-Type字段。
$cookie_COOKIEcookie COOKIE的值。
$document_root当前请求在root指令中指定的值。
$document_uri与$uri相同。
$host请求中的主机头(Host)字段,如果请求中的主机头不可用或者空,则为处理请求的server名称(处理请求的server的server_name指令的值)。值为小写,不包含端口。
$hostname机器名使用 gethostname系统调用的值
$http_HEADERHTTP请求头中的内容,HEADER为HTTP请求中的内容转为小写,-变为_(破折号变为下划线),例如:$http_user_agent(Uaer-Agent的值);
$sent_http_HEADERHTTP响应头中的内容,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
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shuaijie506

您的打赏是我继续分享的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值