赞
踩
自已公司内部的系统,需要修改为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时会用到
修改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;
修改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>
在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
网上查到的各种配置中,很多配置中对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;
这个问题目前只找到了一种解决方案,就是将Tomcat也开启https协议,nginx转发时使用https://协议进行转发,就能完美解决这个问题。
变量名 | 定义 |
---|---|
$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 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。