目录
五、主配置文件/usr/local/nginx/conf/nginx.conf
6.2InstallCert.java(解决httpclient访问https报错---没彻底解决,请直接看6.3)
6.3但是!启动又报错了!No name matching www.aia.nginx1.com found
一、功能
负载均衡、动静分离
二、正向代理和反向代理区别
正向代理是客户端与正向代理在同一局域网,客户端发出请求,正向代理替代客户端向服务器发出请求,服务器不知道谁是真正的客户端,正向代理隐藏了真实的客户端;正向代理一般是客户端架设的,比如在自己的机器上装一个代理软件;正向代理帮助客户访问其无法访问的服务器资源;正向代理代理的是客户端,proxy和client同属一个LAN(局域网);
反向代理是服务器与反向代理在同一局域网,客服端发出请求,反向代理接收请求,反向代理服务器会把我们的请求分发到真实提供服务的各台服务器,反向代理隐藏了真实的服务端;反向代理一般是服务器架设的;反向代理帮助服务器做负载均衡,另外,由于客户端跟真实服务器不直接接触,能起到一定安全防护的作用;反向代理代理的是服务器,proxy和server同属一个LAN(局域网);
三、动静分离
不分离:动态资源和静态资源都放在tomcat中
分离:
四、安装nginx
方式一
docker pull nginx:版本号
方式二
1.安装pcre依赖
下载:
wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz
解压:
tar -xvf pcre-8.37.tar.gz
进入解压后的目录执行命令:
./configure
执行命令:
make && make install
查看版本:
pcre-config --version
make 命令执行不了的同学./configure后最后一行会出现
configure: error: You need a C++ compiler for C++ support.
安装一下这个即可:yum install -y gcc gcc-c++
(安装完毕后在执行 ./configure 在执行make 就OK了我就是这样)
2.安装openssl和zlib依赖
yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
3.安装nginx
nginx一般安装到/usr/local/nginx目录下
//创建一个文件夹
cd /usr/local
mkdir nginx
cd nginx
//下载tar包
wget http://nginx.org/download/nginx-1.13.7.tar.gz
//解压
tar -xvf nginx-1.13.7.tar.gz
//进入解压后的目录
cd nginx-1.13.7
//执行命令
./configure
//执行make命令
make
//执行make install命令
make install
//启动nginx
cd /usr/local/nginx/sbin
./nginx //启动命令
//查看nginx服务,默认1个主进程1个woker进程
ps -ef | grep nginx
nginx有一个主进程和几个工作进程,主进程的主要目的是读取和评估配置并维护工作进程,工作进程会对请求进行实际处理。
//修改nginx防火墙端口配置
firewall-cmd --list-all //查看防火墙开放的端口列表
firewall-cmd --add-service=http --permanent //开放http请求
firewall-cmd --remove-service=http --permanent //移除http请求
firewall-cmd [--zone=public] --add-port=80/tcp --permanent //开放80端口
firewall-cmd --reload //重启防火墙
firewall-cmd --list-all //查看防火墙开放的端口列表
//浏览器访问ip
默认/usr/local/nginx/conf/nginx.conf配置的端口为80,可省略
4.nginx常用命令
cd /usr/local/nginx/sbin
//查看版本
./nginx -v
//启动
./nginx
//重新加载配置文件
./nginx -s reload
//关停
./nginx -s stop
五、主配置文件/usr/local/nginx/conf/nginx.conf
组成部分
//全局块
worker_processes
启动Nginx工作进程的数量,默认1表示nginx只运行一个worker进程,一般设为CPU核心数或CPU核心数-1/+1;
1.9.10版本后也可以设置为worker_processes auto,表示根据cpu核数自动设置;
worker_cpu_affinity
worker_cpu_affinity配置仅对Linux操作系统有效。
Nginx默认没有开启利用多核cpu,我们可以通过增加worker_cpu_affinity配置参数来充分利用多核cpu的性能,将Nginx工作进程绑定到指定的CPU核心,绑定并不是意味着当前nginx进程独占一核心CPU,但是可以保证此进程不会运行在其他核心上,这就极大减少了nginx的工作进程在不同的cpu核心上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,因此可以有效的提升nginx服务器的性能,关键是避免不同的CPU缓存失效。
示例配置
例如:服务器上安装有2颗双核CPU(在系统中显示CPU数量应该是4个) 例1:设定Nginx启用4个进程,那么可以写为: worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; 例2:设定Nginx启用8个进程,那么可以写为: worker_processes 8; worker_cpu_affinity 0001 0010 0100 1000 0001 0010 0100 1000; 紧跟在worker_cpu_affinity命令后的几组数字代表了Nginx开启了多少个进程, 例如开启4个进程,后面对应就有四组数字,每组数字对应一个进程。 每组数字的位数是由CPU的数量所决定的,2个CPU是01,4个CPU是0001,8个CPU是00000001, 有多少个CPU,就有几位数,1表示该CPU可被Nginx使用,0表示该CPU禁用。
如,8核CPU开启2进程,
worker_processes 2;
worker_cpu_affinity 10101010 01010101;
说明:10101010表示开启了第2,4,6,8内核,01010101表示开启了1,3,5,7内核
配置完毕后,重启Nginx。
测试Nginx进程是否能正常分配到多颗CPU上 ,可在另一台机器上通过apache的ab工具进行检测。同时,在服务器上用top命令,按1,就可以看到CPU的工作情况。如果多个CPU的利用率都相差不多,证明Nginx己经成功的设置了worker_cpu_affinity参数。
查看cpu核数
lscpu
cat /proc/cpuinfo | grep 'processor' | wc -l
执行top命令后,按1打开cpu的核心列表
[root@blog conf]$ top top - 18:45:32 up 105 days, 8:41, 3 users, load average: 0.00, 0.00, 0.00 Tasks: 153 total, 1 running, 145 sleeping, 7 stopped, 0 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 15355.3 total, 838.1 free, 1154.0 used, 13363.1 buff/cache MiB Swap: 0.0 total, 0.0 free, 0.0 used. 13873.0 avail Mem ...
worker_processes和worker_connections可以实际的设置nginx的总体最大连接数,比如worker_processes设置为2,worker_connections设置为1024,那么nginx的总体最大连接数就是2048个。但是这些连接数,不仅包含了nginx和客户端的链接,还包含了nginx和被代理的服务端的链接,因此不代表nginx的并发能力是2048,具体设置多少,要根据压测结果确定。不过实际情况中,nginx往往不会成为性能的瓶颈,瓶颈一般都在被代理的服务上(如tomcat)。 作者:java领域 https://www.bilibili.com/read/cv16323124 出处:bilibili
worker_priority
worker_priority表示nginx worker进程优先级设置,默认0,优先级由静态优先级和内核根据进程执行情况所做的动态调整(目前只有±5的调整)共同决定。nice值是进程的静态优先级,它的取值范围是–20~+19,–20是最高优先级,+19是最低优先级。因此,如果用户希望Nginx占有更多的系统资源,那么可以把nice值配置得更小一些,但不建议比内核进程的nice值(通常为–5)还要小。NICE值:nice值应该是熟悉Linux/UNIX的人很了解的概念了,我们都知它是反应一个进程“优先级”状态的值,其取值范围是-20至19,一共40个级别。
worker_rlimit_nofile
单个worker进程打开的最多文件描述符数目。
理论上这个值是最多打开文件数(ulimit -n命令显示的系统最多打开文件数)与nginx工作进程数worker_processes相除。但是nginx调度时分配请求到进程并不是那么的均衡,所以最好与ulimit -n 的值即系统最多打开文件数保持一致,所以假如填写10240,当总并发量达到3-4万时就有进程可能超过10240了,这时会返回502网关错误。
worker_rlimit_nofile如果没设置的话,这个值默认为操作系统最大打开文件数的限制(Linux系统的最大打开文件数默认为1024个,当并发访问量大时很容易遇到error: too many open files,可以调高【一般设为65535个】)。
worker_rlimit_nofile 65535;
如果worker_rlimit_nofile的值小于worker_connections的值,会报如下错误:
worker_connections exceed open file resource limit: xxx
//events块
worker_connections
设置单个工作进程(worker进程)的最大并发连接数,默认1024意味着每个工作进程可以服务1024个客户端/秒,每个工作进程可设的最大值为65535,其值应小于或等于worker_rlimit_nofile(一般设为65535)的值或者系统最大打开文件数(一般设为65535)。
如何设置worker_connections的值?
网上众说纷纭,【建议取各方说法的中间值:10240*3=30720】
如何查看系统的最大打开文件数:
- [root@blog ~]# ulimit -n
- 65535
从client到nginx是长连接,从nginx到server也是长连接。
//http块
http块又包括http全局块和server块
1.http全局块
upstream 配置说明:
默认为轮询策略,如果服务器down掉会自动剔除。
down:表示单前的server暂时不参与负载
Weight:默认为1.weight越大,负载的权重就越大。
max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
fail_timeout: max_fails 次失败后,暂停的时间。
Backup:其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻
fair:按照服务器响应时间分配,时间短的负载的请求多,只需要在upstream中加一个fair即可。
ip_hash:能够将某个ip的请求固定到同一台后端应用服务器,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:
- upstream servertest {
- server 192.168.1.146:8080 down;
- server 192.168.1.146:8081 weight=3;
- server 192.168.1.146:8082;
- server 192.168.1.146:8083 backup;
- ip_hash;
- }
优点:ip_hash算法可以把一个ip映射到一台服务器上,这样可以解决session同步的问题。这样每个访客固定访问一个后端服务器,可以解决session的问题;
缺点:使用ip_hash进行session共享,它的原理是为每个访问者提供一个固定的访问ip,让用户只能在当前访问的服务器上进行操作,保持了session同步的,但是也造成了负载不均衡的问题,如果当前用户访问的服务器挂了的话,那就会出现问题了;
2.server块 (upstream被server块中的location引用)
动静分离
expires参数是配置在location中
server {
listen 80;
server_name 192.168.0.123;#charset koi8-r;
#access_log logs/host.access.log main;
# 根据后缀匹配静态资源,将请求转发到/www/路径下
location ~* \.(jpg|png|css|js|html)$ {
# 使用root+请求路径,在系统里查找资源
# 比如请求的是http://192.168.0.123/static/test.html,请求路径是:/static/test.html,于是查找路径是:/www/static/test.html
root /www/;
}
# 根据请求路径匹配静态资源,也是采用root+请求路径的方式查找资源的,请求是:http://192.168.0.123/static/test.html,请求路径是:/static/test.html,root+请求路径是:/www/static/test.html
location /static/ {
root /www/;
# 开启目录浏览功能,请求是目录的时候,会显示目录下的内容
autoindex on;
# 过期时间是5天,未过期的时候状态码304,浏览器请求会走缓存
expires 5d;
}
#
#error_page 404 /404.html;# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
root和alias区别:
使用root时访问http://192.168.17.129/www/a.html代理到http://192.168.17.129/data/www/a.html;
使用alias时访问http://192.168.17.129/www/a.html代理到http://192.168.17.129/data/a.html;
root和proxy_pass区别:
root配置代理路径时,会在代理路径后拼接location配置的路径;
root配置的路径是nginx作为服务器后的根目录,所以root后面跟的是个文件夹名,当浏览器中输入自己的服务器ip后,显示的是该目录下的index.html。
proxy_pass后面跟的是ip和端口。
proxy_pass总结:
proxy_pass也可以不引用upstream但此时只能代理到单台服务器
一、proxy_pass不带路径末尾有斜杠
location /api/ {
proxy_pass http://127.0.0.1:8000/;
}
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/test二、proxy_pass不带路径末尾无斜杠
location /api/ {
proxy_pass http://127.0.0.1:8000;
}
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/api/test三、proxy_pass包含路径,且末尾有斜杠
location /api/ {
proxy_pass http://127.0.0.1:8000/user/;
}
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/user/test四、proxy_pass包含路径,末尾无斜杠
location /api/ {
proxy_pass http://127.0.0.1:8000/user;
}
请求地址:http://localhost/api/test
转发地址:http://127.0.0.1:8000/usertestlocation ^~和location ~ 区别
超时设置
#【Nginx中的超时设置】
#前端axios设置的超时时间可以 ≥ 前端与Nginx的keepalive_timeout ≥ Nginx与后端的proxy_read_timeout
#“keepalive_timeout”:ng服务器与客户端之间保持连接的超时时间,单位为秒,默认75s(若客户端75秒内无新请求Nginx会主动断开连接),连接闲置(无数据传输)时生效,建议60~120s,平衡连接复用与资源释放
#“proxy_read_timeout”:代理服务器从后端服务器读取数据的超时时间,单位为秒,默认60s,若后端实际处理时间超过此值,Nginx会强制断开代理连接并返回504错误,根据后端API平均响应时间调整,通常60~300s足够。
# proxy_read_timeout大于keepalive_timeout不会导致连接异常,Nginx 会在数据传输期间暂缓keepalive_timeout的计数,待响应完成后再恢复闲置计时
# 若需最大化连接复用效率,可设置 keepalive_timeout略大于后端服务的平均响应时间(例如 keepalive_timeout 120s + proxy_read_timeout 60s),避免频繁重建连接
#“client_body_timeout”:客户端向ng服务器发送请求体(如 POST 数据、文件上传)的超时时间
#“client_header_timeout”:客户端向ng服务器发送请求头的超时时间,单位为秒,若超时未收到完整请求头,Nginx返回HTTP 408(Request Time-out)
#“send_timeout”:ng服务器向前端即客户端发送响应数据的超时时间,单位为秒。
#“proxy_connect_timeout”:ng服务器与后端服务器建立连接超时时间,单位为秒。
#“proxy_send_timeout”:ng服务器向后端服务器发送请求数据的超时时间,单位为秒。
详见另一篇文章记录的Gener的nginx配置实例。
高可用主备模式
需求
为防止nginx挂掉,可采用主备模式。
- 需要两台nginx服务器
- 需要keepalived服务(也可用于mysql等的主备切换)
- 需要虚拟ip
keepalived安装
在两台nginx所在服务器上都安装keepalived
yum -y install keepalived
rpm -q -a keepalived //查看是否安装成功
在/etc/keepalived下内含配置文件keepalived.conf,用于主从的配置
keepalived.conf配置(重要)
通过修改keepalived.conf来实现Nginx的高可用,修改后的keepalived.conf内容(这里是主的配置,从的配置需按照注释作对应修改):
# 全局定义
global_defs {
notification_email { # keepalived发生故障切换时邮件发送的目标邮箱,可以按行区分写
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc # 发邮件的地址
smtp_server 192.168.0.123 # 邮件服务器地址
smtp_connect_timeout 30 # 邮件服务器连接timeout
# 路由id,当前安装的keepalived节点主机的标识符,主备机不同,保持全局唯一
router_id LVS_DEVEL
# 设置运行脚本默认用户和组。如果没有指定,则默认用户为keepalived_script(需要该用户存在),否则为root用户。默认groupname同username
script_user root
# 如果脚本路径的任一部分对于非root用户来说,都具有可写权限,则不会以root身份运行脚本
enable_script_security
}
# 检测Nginx是否还存活的脚本
vrrp_script check_nginx {
# 脚本文件的位置
script "/usr/local/src/nginx_check.sh"
interval 10 # Keepalived会每隔10s执行一次脚本检查Nginx进程是否还在。如果Nginx进程的数量等于0,尝试重启Nginx,等待10s让Nginx启动完成,再次检测Nginx的进程数量,如果还是0,就把Keepalived服务也停掉,如果Keepalived服务不停掉,虚拟IP不能自动飘到另一台机器上。如果Nginx在10s内正常启动了,那么就当什么都没有发生。
weight 20 # 设置当前服务器的权重,正负皆可,设置方法:https://blog.youkuaiyun.com/weixin_42558057/article/details/82722516
}
# 虚拟IP的配置
vrrp_instance VI_1 {
state MASTER # 表示当前服务器是MASTER还是BACKUP
interface ens33 # 绑定的网卡名称,ifconfig查看,主备机根据各自的分别配置
virtual_router_id 51 # 主、备机的virtual_router_id必须相同,范围:0-255
priority 100 # 主、备机取不同的优先级,主机值较大,备份机值较小,正数
advert_int 1 # 每隔多久发送一次心跳,默认是1秒
# 权限校验,防止非法节点的进入,主备需要一致
authentication {
auth_type PASS # PASS固定写法
auth_pass 1357 # 四位数字即可
}
# 虚拟IP地址,主从保持一致
virtual_ipaddress {
192.168.0.222
}
# 指定监控脚本
track_script {
# 这里的check_nginx对应上面的vrrp_script的名字
check_nginx
}
}
关于weight的配置:
在Keepalived集群中,其实 并没有严格意义上的主、备节点,虽然可以在Keepalived配置文件中设置“state”选项为“MASTER”状态,但是这并不意味着此节点一直就是Master角色。控制节点角色的是Keepalived配置文件中的“priority”值,但并它并不控制所有节点的角色,另一个能改变节点角色的是在vrrp_script模块中设置的“weight”值,这两个选项对应的都是一个整数值,其中“weight”值可以是个负整数,一个节点在集群中的角色就是通过这两个值的大小决定的。 在一个一主多备的Keepalived集群中,“priority”值最大的将成为集群中的Master节点,而其他都是Backup节点。在Master节点发生故障后,Backup节点之间将进行“民主选举”,通过对节点优先级值“priority”和““weight”的计算,选出新的Master节点接管集群服务。 在vrrp_script模块中,如果不设置“weight”选项值,那么集群优先级的选择将由Keepalived配置文件中的“priority”值决定,而在需要对集群中优先级进行灵活控制时,可以通过在vrrp_script模块中设置“weight”值来实现。下面列举一个实例来具体说明。 假定有A和B两节点组成的Keepalived集群,在A节点keepalived.conf文件中,设置“priority”值为100,而在B节点keepalived.conf文件中,设置“priority”值为80,并且A、B两个节点都使用了“vrrp_script”模块来监控mysql服务,同时都设置“weight”值为10,那么将会发生如下情况。 在两节点都启动Keepalived服务后,正常情况是A节点将成为集群中的Master节点,而B自动成为Backup节点,此时将A节点的mysql服务关闭,通过查看日志发现,并没有出现B节点接管A节点的日志,B节点仍然处于Backup状态,而A节点依旧是Master状态,在这种情况下整个HA集群将失去意义。 下面就分析一下产生这种情况的原因,这也就是Keepalived集群中主、备角色选举策略的问题。下面总结了在Keepalived中使用vrrp_script模块时整个集群角色的选举算法,由于“weight”值可以是正数也可以是负数,因此,要分两种情况进行说明。1.“weight”值为正数时
在vrrp_script中指定的脚本如果检测成功,那么Master节点的权值将是“weight值与”priority“值之和,如果脚本检测失败,那么Master节点的权值保持为“priority”值,因此切换策略为:
Master节点“vrrp_script”脚本检测失败时,如果Master节点“priority”值小于Backup节点“weight值与”priority“值之和,将发生主、备切换。
Master节点“vrrp_script”脚本检测成功时,如果Master节点“weight”值与“priority”值之和大于Backup节点“weight”值与“priority”值之和,主节点依然为主节点,不发生切换。
所以:主机priority设为100,从机priority设为90,主从机weight都设为20即可。
2.“weight”值为负数时
在“vrrp_script”中指定的脚本如果检测成功,那么Master节点的权值仍为“priority”值,当脚本检测失败时,Master节点的权值将是“priority“值与“weight”值之差,因此切换策略为:
节点“vrrp_script”脚本检测失败时,如果Master节点“priority”值与“weight”值之差小于Backup节点“priority”值,将发生主、备切换。
Master节点“vrrp_script”脚本检测成功时,如果Master节点“priority”值大于Backup节点“priority”值时,主节点依然为主节点,不发生切换。
在熟悉了Keepalived主、备角色的选举策略后,再来分析一下刚才实例,由于A、B两个节点设置的“weight”值都为10,因此符合选举策略的第一种,在A节点停止Mysql服务后,A节点的脚本检测将失败,此时A节点的权值将保持为A节点上设置的“priority”值,即为100,而B节点的权值将变为“weight”值与“priority”值之和,也就是90(10+80),这样就出现了A节点权值仍然大于B节点权值的情况,因此不会发生主、备切换。
对于“weight”值的设置,有一个简单的标准,即“weight”值的绝对值要大于Master和Backup节点“priority”值之差。对于上面A、B两个节点的例子,只要设置“weight”值大于20即可保证集群正常运行和切换。由此可见,对于“weight值的设置,要非常谨慎,如果设置不好,将导致集群角色选举失败,使集群陷于瘫痪状态。
新建nginx_check.sh脚本文件:
(mysql等主备集群的脚本文件可以自行百度)/usr/local/nginx/sbin/nginx根据nginx安装位置配置
#!/bin/bash
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
systemctl stop keepalived
fi
fi
之后,需要给这个脚本执行权限:chmod 744 /usr/local/src/nginx_check.sh,否则脚本无法执行,注意,这里不能给777权限,如果给777,在执行脚本的时候,会提示如下信息:
Apr 3 11:45:34 bogon Keepalived_vrrp[21615]: Unsafe permissions found for script '/usr/local/src/nginx_check.sh'.
Apr 3 11:45:34 bogon Keepalived_vrrp[21615]: Disabling track script check_nginx due to insecure
还需要关闭selinux,临时关闭命令:setenforce 0,重启后又会打开。
永久关闭命令:sed -i “s/^SELINUX=.*/SELINUX=disabled/g” /etc/selinux/config,然后重启。
keepalived启动命令:systemctl start keepalived.service
查看是否启动成功:ps -ef|grep keepalived
启动不成功,参考:Keepalived的详细配置与使用_Su丶因陀罗的博客-优快云博客_keepalived配置
keepalived基本命令_Male晓的博客-优快云博客_查看keepalived状态
为了测试这个脚本,花了挺久的,说下里面的坑和排查方法。
使用两个窗口连接服务器,一边执行Keepalived的启动命令,一边查看日志,使用“tail -f /var/log/messages”可以查看到Keepalived的启动日志
如果日志中明显提示有错误信息,根据日志提示的错误进行修改即可,常见的有:unknown keyword xxx,这种一般是单词拼错了,或者是前后的变量不对应(比如,track_script里的脚本名称要和vrrp_script的名称对应,否则找不到脚本),还有可能是复制粘贴带过来的特殊符号问题(Windows里的换行符和Unix里的换行符不一致问题)
nginx_check.sh这个脚本要赋予执行权限,但是不能赋予777权限,要想检查nginx_check.sh对不对,可以手动执行一次,看看功能正常不正常,如果功能正常,说明检测脚本没问题,否则根据报错修改脚本
关闭selinux
保证脚本正确之后,再往后做。
————————————————
版权声明:本文为优快云博主「王劭阳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_36059561/article/details/115386069
下面进行测试:
分别启动两台服务器上的Nginx和Keepalived,通过浏览器访问虚拟IP,可以看到Nginx的界面,这时候,我们关掉主的Nginx和Keepalived,再次刷新页面,Nginx依旧可以访问。当主挂掉后,虚拟IP才会绑定到Nginx的从服务器,在Nginx的从服务器上,使用ip a命令,可以看到在ens33网卡下,其实绑定了虚拟IP。
nginx原理
Nginx的进程有Master进程和Worker进程。
Master负责分配请求任务,Worker负责执行具体的任务,每个worker都是独立进程不需要加锁。
一个Master对应多个Worker,当一个任务出现的时候,Master下的多个空闲的Worker参与争抢任务。
正是因为一个Master下有多个Worker,才能保证Nginx可以不重启直接重新加载配置文件,当执行nginx -s reload的时候,空闲的Worker会重启,工作的Worker还是按照原来的配置运行,当它处理完之后,它也会按照新的配置进行重启,所以Nginx才能不停机更新。
Nginx和Redis一样都采用io多路复用机制,通过异步(多个worker)非阻塞(每个worker作为独立进程)的方式处理请求。
一个请求会占用2个或者4个Worker的连接数(worker_connections)。
2个:只访问静态资源,客户端→Worker→客户端
4个:如果有动态资源,客户端→Worker→客户端,Worker→Tomcat→Worker
静态资源服务器的最大并发数:worker_connection * worker_process / 2。
如果是作为反向代理服务器,最大并发数:worker_connection * worker_process / 4。
六、疑难问题
location中proxy_set_header的设置问题
Nginx的proxy_set_header设置问题_王景清的博客-优快云博客_nginx proxy_set_header
location中proxy_redirect 的设置问题
nginx 之 proxy_redirect详解 - 苍青浪 - 博客园
七、补充
测试结果:
nginx请求目标真实服务器上的静态资源/不进行登录拦截的页面,地址栏路径不变,设置的cookie域名是nginx域名。
若浏览器地址栏域名因目标真实服务器的重定向行为而改变,则记录的cookie域名将是重定向到的域名。
测试发现:
nginx代理的请求不发生重定向(浏览器地址栏不变化),cookie域名是nginx域名,且单个服务器在一段时间内被多次被轮询到每次产生的sessionid均不相同;若只有一个服务器提供服务,其它服务器均配置down,则sessionid在有效期不会变。
八、nginx+https,配置openssl证书
除了自己本文的笔记,还可以参考这个文章对比着来。
https://www.cnblogs.com/acool/p/4933325.html
1.配置openssl
查看 openssl 版本、安装位置
查看openssl.cnf配置文件
针对于上图的所示的文件结构,创建对应的文件目录和文件,安全起见,先检查目录、文件是否存在,不存在再创建
创建缺失目录和文件
certs,crl,newcerts,private4个目录若不存在请自行创建,
[root@k8s-master CA]# mkdir -pv /etc/pki/CA/{certs,crl,newcerts,private}
mkdir: created directory ‘/etc/pki/CA/certs’
mkdir: created directory ‘/etc/pki/CA/crl’
mkdir: created directory ‘/etc/pki/CA/newcerts’
mkdir: created directory ‘/etc/pki/CA/private’
[root@k8s-master CA]# ll
total 0
drwxr-xr-x. 2 root root 6 Apr 3 14:24 certs
drwxr-xr-x. 2 root root 6 Apr 3 14:24 crl
drwxr-xr-x. 2 root root 6 Apr 3 14:24 newcerts
drwxr-xr-x. 2 root root 6 Apr 3 14:24 private
[root@k8s-master CA]#
这里只用创建缺失文件(crlnumber文件不用创建)。
touch /etc/pki/CA/{serial,index.txt}
使用tree 命令查看目录结构(tree命令用不了,我用的是ls命令)
修改配置文件。编辑openssl.cnf中的一些选项。
unique_subject = no (这样一个CA可以同时签多张证书)
countryName = optional(把这些参数的匹配规则改为可选)
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
2.指定根证书编号--即CA编号
根证书--CA,是用来生成服务器证书的,证书之间是存在链式关系的,当信任根证书时,由其衍生出来的证书都会被信任。从根证书开始每一个证书都有一个对应的编号,是通过serial的值来进行维护的,首先指明证书的开始编号。
echo 01 >> serial
3.生成CA(根证书)私钥
使用umask 077使得之后生成文件的默认权限为077,使用openssl工具生成 4096位的rsa秘钥,该秘钥存放在/etc/pki/CA/private/cakey.pem 中
umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096
4.生成CA证书(根证书)
使用刚生成的私钥生成CA证书
req: 这是一个大命令
-new: 表示新生成一个证书请求
-x509: 直接输出证书
-key: 生成证书请求时用到的私钥文件 /etc/pki/CA/private/cakey.pem
-out:输出文件 /etc/pki/CA/cacert.pem
openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3650
中间会要求输入地址,邮箱,公司等名字,由于是自颁发,随便输入即可,
hostname:https://www.aia.nginx1.com:30888
补充:吊销证书(之前生成的域名没写全,端口和前面的都没写,这里写下怎么吊销--吊销了还能用无语了)
# 创建证书吊销列表(crl)序列号文件 echo 00 > /etc/pki/CA/crlnumber [root@k8s-master CA]# ll total 24 -rw-------. 1 root root 2171 Mar 31 16:21 cacert.pem drwxr-xr-x. 2 root root 6 Aug 4 2017 certs drwxr-xr-x. 2 root root 6 Aug 4 2017 crl -rw-r--r--. 1 root root 3 Apr 3 13:37 crlnumber -rw-------. 1 root root 113 Mar 31 16:53 index.txt -rw-------. 1 root root 21 Mar 31 16:53 index.txt.attr -rw-r--r--. 1 root root 0 Mar 31 15:45 index.txt.old drwxr-xr-x. 2 root root 20 Mar 31 16:53 newcerts drwx------. 2 root root 23 Mar 31 16:03 private -rw-------. 1 root root 3 Mar 31 16:53 serial -rw-r--r--. 1 root root 3 Mar 31 16:00 serial.old [root@k8s-master CA]# cat index.txt V 240330085318Z 01 unknown /C=cn/ST=ShangHai/O=GenerSoft/CN=aia.nginx.test1.com/emailAddress=15893317063@qq.com [root@k8s-master CA]# ll total 8 -rw-------. 1 root root 7390 Mar 31 16:53 01.pem [root@k8s-master newcerts]# openssl ca -revoke /etc/pki/CA/newcerts/01.pem Using configuration from /etc/pki/tls/openssl.cnf Revoking Certificate 01. Data Base Updated [root@k8s-master newcerts]# cd .. [root@k8s-master CA]# ll total 32 -rw-------. 1 root root 2171 Mar 31 16:21 cacert.pem drwxr-xr-x. 2 root root 6 Aug 4 2017 certs drwxr-xr-x. 2 root root 6 Aug 4 2017 crl -rw-r--r--. 1 root root 3 Apr 3 13:37 crlnumber -rw-r--r--. 1 root root 126 Apr 3 13:47 index.txt -rw-r--r--. 1 root root 21 Apr 3 13:47 index.txt.attr -rw-------. 1 root root 21 Mar 31 16:53 index.txt.attr.old -rw-------. 1 root root 113 Mar 31 16:53 index.txt.old drwxr-xr-x. 2 root root 20 Mar 31 16:53 newcerts drwx------. 2 root root 23 Mar 31 16:03 private -rw-------. 1 root root 3 Mar 31 16:53 serial -rw-r--r--. 1 root root 3 Mar 31 16:00 serial.old [root@k8s-master CA]# cat index.txt R 240330085318Z 230403054758Z 01 unknown /C=cn/ST=ShangHai/O=GenerSoft/CN=aia.nginx.test1.com/emailAddress=15893317063@qq.com [root@k8s-master CA]# openssl ca -gencrl -out /etc/pki/CA/crl.pem Using configuration from /etc/pki/tls/openssl.cnf [root@k8s-master CA]# ll total 40 -rw-------. 1 root root 2171 Mar 31 16:21 cacert.pem drwxr-xr-x. 2 root root 6 Aug 4 2017 certs drwxr-xr-x. 2 root root 6 Aug 4 2017 crl -rw-r--r--. 1 root root 3 Apr 3 13:50 crlnumber -rw-r--r--. 1 root root 3 Apr 3 13:37 crlnumber.old -rw-r--r--. 1 root root 1117 Apr 3 13:50 crl.pem -rw-r--r--. 1 root root 126 Apr 3 13:47 index.txt -rw-r--r--. 1 root root 21 Apr 3 13:47 index.txt.attr -rw-------. 1 root root 21 Mar 31 16:53 index.txt.attr.old -rw-------. 1 root root 113 Mar 31 16:53 index.txt.old drwxr-xr-x. 2 root root 20 Mar 31 16:53 newcerts drwx------. 2 root root 23 Mar 31 16:03 private -rw-------. 1 root root 3 Mar 31 16:53 serial -rw-r--r--. 1 root root 3 Mar 31 16:00 serial.old [root@k8s-master CA]# cat crl.pem -----BEGIN X509 CRL----- MIIDEDCB+QIBATANBgkqhkiG9w0BAQsFADCBoDELMAkGA1UEBhMCY24xETAPBgNV BAgMCFNoYW5nSGFpMREwDwYDVQQHDAhTaGFuZ0hhaTESMBAGA1UECgwJR2VuZXJT b2Z0MRYwFAYDVQQLDA1HZW5lclNvZnQtUGxtMRwwGgYDVQQDDBNhaWEubmdpbngu dGVzdDEuY29tMSEwHwYJKoZIhvcNAQkBFhIxNTg5MzMxNzA2M0BxcS5jb20XDTIz MDQwMzA1NTAzMloXDTIzMDUwMzA1NTAzMlowFDASAgEBFw0yMzA0MDMwNTQ3NTha oA4wDDAKBgNVHRQEAwIBADANBgkqhkiG9w0BAQsFAAOCAgEAwmgF241tot0osTrm GDLb4hYJNAitSA+2PvIjlK2lfyQX4Dzow2GqKUGC4iYyqGhGzmgBGWfX1++zHkZ7 e4rvhQiMMs3SCvs3iiGYGlVZ1bta+2pYraoZOBlvGaf+eu6lE/1A47xEWVy9O6n4 cXt4AQT21jtekKwuHZe79Us8OkrqYNo2jxTcfZ3EmWX32/DX/dt5EKmBtY7tfsBn Pd/n+OsvXPeZ4AGJZhrS3S5qKtOfaJZs+tMA7CuXGAi4DAVdaWPrVbVLwc5GwiLv yayVF35nbLgzicjNuzeOTWSXqQB2ai9cxQAZgnsN1v7X5OIR/3GCl8n10fAZT7sO 4nJWNatb6OvOExu3Sg8rbdGUL/ygp6Wew+dA7koqkrQw/ESrGXpvUcZQWD8Etu9z XlaGCMw9a1LQ/EhUQZBtrJZLrujE3stECGMzCKeb2EPRQBo0ycxKHzC/V/u+j/1z 728a9zJ7wGEj9O/PDShsbG+2nnOENuvjzGVNXYyiT8Fp7itjxtEzBJh98R5TKEiI 1PelO54Gp5VUsQi7wvUDvXAkOmYcYPy94n6VJzEXx5PIlSEN+y/4O0sa1+PVgxLb z3mjBBLVNCAp1EFWcZW9WHb46OvI+nKwFsXtgfXCrlM/nQRmXESz5KdDYMHxe1Gk eE9PeenoeauyOrGf/WxppOuIPL4= -----END X509 CRL----- [root@k8s-master CA]# openssl crl -in /etc/pki/CA/crl.pem -noout -text Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: /C=cn/ST=ShangHai/L=ShangHai/O=GenerSoft/OU=GenerSoft-Plm/CN=aia.nginx.test1.com/emailAddress=15893317063@qq.com Last Update: Apr 3 05:50:32 2023 GMT Next Update: May 3 05:50:32 2023 GMT CRL extensions: X509v3 CRL Number: 0 Revoked Certificates: Serial Number: 01 Revocation Date: Apr 3 05:47:58 2023 GMT Signature Algorithm: sha256WithRSAEncryption c2:68:05:db:8d:6d:a2:dd:28:b1:3a:e6:18:32:db:e2:16:09: 34:08:ad:48:0f:b6:3e:f2:23:94:ad:a5:7f:24:17:e0:3c:e8: c3:61:aa:29:41:82:e2:26:32:a8:68:46:ce:68:01:19:67:d7: d7:ef:b3:1e:46:7b:7b:8a:ef:85:08:8c:32:cd:d2:0a:fb:37: 8a:21:98:1a:55:59:d5:bb:5a:fb:6a:58:ad:aa:19:38:19:6f: 19:a7:fe:7a:ee:a5:13:fd:40:e3:bc:44:59:5c:bd:3b:a9:f8: 71:7b:78:01:04:f6:d6:3b:5e:90:ac:2e:1d:97:bb:f5:4b:3c: 3a:4a:ea:60:da:36:8f:14:dc:7d:9d:c4:99:65:f7:db:f0:d7: fd:db:79:10:a9:81:b5:8e:ed:7e:c0:67:3d:df:e7:f8:eb:2f: 5c:f7:99:e0:01:89:66:1a:d2:dd:2e:6a:2a:d3:9f:68:96:6c: fa:d3:00:ec:2b:97:18:08:b8:0c:05:5d:69:63:eb:55:b5:4b: c1:ce:46:c2:22:ef:c9:ac:95:17:7e:67:6c:b8:33:89:c8:cd: bb:37:8e:4d:64:97:a9:00:76:6a:2f:5c:c5:00:19:82:7b:0d: d6:fe:d7:e4:e2:11:ff:71:82:97:c9:f5:d1:f0:19:4f:bb:0e: e2:72:56:35:ab:5b:e8:eb:ce:13:1b:b7:4a:0f:2b:6d:d1:94: 2f:fc:a0:a7:a5:9e:c3:e7:40:ee:4a:2a:92:b4:30:fc:44:ab: 19:7a:6f:51:c6:50:58:3f:04:b6:ef:73:5e:56:86:08:cc:3d: 6b:52:d0:fc:48:54:41:90:6d:ac:96:4b:ae:e8:c4:de:cb:44: 08:63:33:08:a7:9b:d8:43:d1:40:1a:34:c9:cc:4a:1f:30:bf: 57:fb:be:8f:fd:73:ef:6f:1a:f7:32:7b:c0:61:23:f4:ef:cf: 0d:28:6c:6c:6f:b6:9e:73:84:36:eb:e3:cc:65:4d:5d:8c:a2: 4f:c1:69:ee:2b:63:c6:d1:33:04:98:7d:f1:1e:53:28:48:88: d4:f7:a5:3b:9e:06:a7:95:54:b1:08:bb:c2:f5:03:bd:70:24: 3a:66:1c:60:fc:bd:e2:7e:95:27:31:17:c7:93:c8:95:21:0d: fb:2f:f8:3b:4b:1a:d7:e3:d5:83:12:db:cf:79:a3:04:12:d5: 34:20:29:d4:41:56:71:95:bd:58:76:f8:e8:eb:c8:fa:72:b0: 16:c5:ed:81:f5:c2:ae:53:3f:9d:04:66:5c:44:b3:e4:a7:43: 60:c1:f1:7b:51:a4:78:4f:4f:79:e9:e8:79:ab:b2:3a:b1:9f: fd:6c:69:a4:eb:88:3c:be [root@k8s-master CA]# [root@k8s-master CA]# cat crlnumber 01 [root@k8s-master CA]#
但是重启nginx后还是可以用https访问到,干脆直接删掉去球。
上面生成CA证书的命令会让人迷惑,因为生成证书其实一般需要经过三个步骤:
1.生成秘钥 xxx.pem
2.通过秘钥 xxx.pem 生成证书请求文件 xxx.csr
3.通过证书请求文件 xxx.csr 生成最终的证书 xxx.crt
但是上面的命令将第2.和3.步杂糅在了一起,上面命令等价于
//生成证书请求文件
openssl req -new -out /etc/pki/CA/req.csr -key /etc/pki/CA/private/cakey.pem
// -in 使用证书请求文件生成证书,-signkey 指定私钥,这是一个还没搞懂的参数
openssl x509 -req - in /etc/pki/CA/req.csr -out /etc/pki/CA/cacert.pem -signkey /etc/pki/CA/private/cakey.pem -days 3650
5.生成服务端证书
5.1生成服务端私钥.pem
首先我创建并进入了~/aiaNginxTest1Com目录
进入创建的目录,然后生成服务端的私钥
openssl genrsa -out aiaNginxTest1Com.pem 4096
5.2生成服务端证书请求文件.csr
继续在上方创建的~/aiaNginxTest1Com目录中,执行命令
-out 指定名字为aiaNginxTest1Com.csr
-subj 指定的信息要与签署的根证书信息一样
openssl req -new -key aiaNginxTest1Com.pem -out aiaNginxTest1Com.csr -days 365 -subj "/C=cn/ST=ShangHai/L=ShangHai/O=GenerSoft/CN=aia.nginx.test1.com/emailAddress=15893317063@qq.com"
-subj 填入的信息中C和ST和L和O等一定要与签署的根证书一样,如果忘记了根证书乱填了什么,可以通过如下指令进行查询
# /etc/pki/CA/cacert.pem是之前生成的根证书CA的路径 openssl x509 -in /etc/pki/CA/cacert.pem -noout -subject
5.3生成服务端证书.crt
执行以下命令之后就能得到证书文件aiaNginxTest1Com.crt,这就是用于发送给客户端的证书
openssl ca -in aiaNginxTest1Com.csr -out aiaNginxTest1Com.crt -days 365
6.NGINX配置ssl
6.1单向认证
挪生成的服务端证书和秘钥以及证书请求文件的存放地址,从~/aiaNginxTest1Com挪到nginx容器配置的数据卷/opt/nginx/对应的/home/roo/nfs/data/default-nginx-resource-storage-pvc-9a1cbd70-0a9a-4fef-907d-64b57d25e7fb文件夹中。可删除无用的文件夹 ~/aiaNginxTest1Com。
由于我的nginx是在k8s容器中,所以在kube-sphere界面中修改nginx.conf配置文件:
修改后重启nginx容器,访问
要想使用注册证书时配置的域名(需要在本机的hosts文件配置域名映射),否则:
需要在本机的hosts文件配置域名映射,才可以访问到:
公网注册的CA中的域名需要再注册到公网DNS中才能被公网访问,是付费的。
我已经生成出来了是免费的openssl的,是不是免费的这种
注册进CA证书的域名 和 注册进DNS系统中的域名
可以不一样?而公网的必须一样。
也可以把根证书(cacert.pem)通过chrome加以安装信任。
6.2InstallCert.java(解决httpclient访问https报错---没彻底解决,请直接看6.3)
由于cas客户端的以下配置,在重定向到cas服务端的时候需要发起https请求。java代码向cas发起了https重定向请求,所以需要配置一下类似在浏览器信任一下证书,正式的https证书应该就不用配置了。
https://www.cnblogs.com/huang-dayu/p/8446508.html
InstallCert.java:
/*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.*;
import javax.net.ssl.*;
public class InstallCert {
public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
return;
}
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[] {tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1 " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(" md5 " + toHexString(md5.digest()));
System.out.println();
}
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
编译:javac InstallCert.java
运行:java InstallCert 要访问的网址
最后面会输出:
Enter certificate to add to trusted keystore or 'q' to quit: [1]
输入1,然后直接回车,会在相应的目录下产生一个名为‘jssecacerts’的证书。将证书copy到$JAVA_HOME/jre/lib/security目录下。
6.3但是!启动又报错了!No name matching www.aia.nginx1.com found
最后暂时解决方法(启动类添加如下代码,静态块中启动就运行,不再需要标题6.2的操作):
将来通过cas客户端的代码重定向到cas的https请求,完全可以绕过https验证,因为不是在浏览器发起访问的,有一定的安全性了。
static {
disableSslVerification();
}
private static void disableSslVerification() {
try {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
6.4nginx开启双向认证
因为是双向认证,不仅客户端要认证服务端,服务端也需要认证客户端,所以相较于单向认证,会多出以下2个配置参数:
ssl_verify_client on
表示开启双向认证,服务端也要认证客户端,该参数默认是off
关闭。ssl_client_certificate
配置客户端公钥证书存放的路径位置。
7.其它
7.1客户端证书
除了服务端证书和CA根证书之外,还有一种类型叫做客户端证书,这个的作用是用来验证客户的身份,在极少数的情况下会用到,比如说网银限制客户在某台机器上进行登陆,很久之前银行提供的u盾的作用就是为了提供客户端证书而存在的。总之,证书的作用就是用来验证身份。
7.2证书作用补充
-
A和B通信需要将彼此的公钥传递给对方,但是直接传递公钥不安全。
-
通过将公钥传递给认证机构,认证机构对公钥进行签名(私钥加密,公钥解密)并加上一些属性信息。
-
CA机构将证书制作完成后再返还给用户。
-
用户将证书发送给需要通信的一方,对方通过使用CA机构的公钥来进行解密得到他的公钥。