NGINX学习记录

目录

一、功能 

二、正向代理和反向代理区别

三、动静分离

四、安装nginx

方式一

方式二

1.安装pcre依赖

2.安装openssl和zlib依赖

3.安装nginx

 4.nginx常用命令

五、主配置文件/usr/local/nginx/conf/nginx.conf

组成部分

//全局块

//events块

//http块

动静分离

root和alias区别:

root和proxy_pass区别:

proxy_pass总结:

高可用主备模式

需求

keepalived安装

keepalived.conf配置(重要) 

新建nginx_check.sh脚本文件:

nginx原理

六、疑难问题

七、补充 

八、nginx+https,配置openssl证书

1.配置openssl

2.指定根证书编号--即CA编号

3.生成CA(根证书)私钥

4.生成CA证书(根证书)

5.生成服务端证书

5.1生成服务端私钥.pem

5.2生成服务端证书请求文件.csr

5.3生成服务端证书.crt

6.NGINX配置ssl

6.1单向认证

6.2InstallCert.java(解决httpclient访问https报错---没彻底解决,请直接看6.3)

6.3但是!启动又报错了!No name matching www.aia.nginx1.com found

6.4nginx开启双向认证

7.其它

7.1客户端证书

7.2证书作用补充


一、功能 

负载均衡、动静分离

二、正向代理和反向代理区别

正向代理是客户端与正向代理在同一局域网,客户端发出请求,正向代理替代客户端向服务器发出请求,服务器不知道谁是真正的客户端,正向代理隐藏了真实的客户端;正向代理一般是客户端架设的,比如在自己的机器上装一个代理软件;正向代理帮助客户访问其无法访问的服务器资源;正向代理代理的是客户端,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_processesworker_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

如何查看系统的最大打开文件数:

  1. [root@blog ~]# ulimit -n
  2. 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配置中定义的:

  1. upstream servertest {  
  2.     server 192.168.1.146:8080 down;   
  3.     server 192.168.1.146:8081 weight=3;  
  4.     server 192.168.1.146:8082;  
  5.     server 192.168.1.146:8083 backup; 
  6.     ip_hash;
  7. }  

优点: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/usertest

高可用主备模式

需求

为防止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.csdn.net/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丶因陀罗的博客-CSDN博客_keepalived配置

keepalived基本命令_Male晓的博客-CSDN博客_查看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
保证脚本正确之后,再往后做。
————————————————
版权声明:本文为CSDN博主「王劭阳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/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设置问题_王景清的博客-CSDN博客_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机构的公钥来进行解密得到他的公钥。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值