Nginx配置技巧二

标签: Nginx 分类: 后台服务 创建时间:2020-03-08 04:37:59 更新时间:2023-10-20 11:23:26

1.设置文件上传大小

client_header_buffer_size

2.nginx配置https

3.日志格式

log_format 设置日志格式

1
2
3
4
5
6
## 设置日志格式
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
## 启用日志
access_log logs/access_log.log main;

4.配置多个域名

nginx中可以配置多个域名,可以将多个域名解析到同一个ip地址上面,然后通过server_name进行区分。我这里有一个奇怪的问题,就是如果你在阿里云中配置了dev.proeheng.net,那么你再配置shopdev.proheng.net,那么结果就是所有通过shopdev.proheng.net的请求也都转发到了dev.proheng.net,也就是你配置的shopdev.proheng.net没有用了。如果配置了shop.dev.proheng.net就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 80;
server_name shopdev.proheng.net;
root /cloud/dev/PhShop;
index index.php index.html index.htm;

#access_log logs/host.access.log main;

location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php?s=/$1 last;
}
}

location ~ \.(php|html)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi.conf;
}

}

5.配置ssl实现https访问

(1) 申请阿里云ssl证书,下载对应版本的ssl证书,比如Apache / IIS / Nginx 都有对应的证书版本。

(2) 上传证书到指定目录,比如:/cloud/dev/ssl

(3) 编写nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
listen 443 ssl;
ssl on;
ssl_certificate //cloud/dev/ssl/ssl.pem;
ssl_certificate_key //cloud/dev/ssl/ssl.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
}
## 将http重定向到https,rewrite不能和443写在一起,要不就一直跳转了,形成了死循环。
server {
listen 80;
server_name xxx.com www.xxx.com;
rewrite ^(.*) https://$host$1 permanent;
}

6.nginx条件判断if

7.转发TCP流量

nginx不仅可以转发http流量,还可以转发tcp的流量(这个问题也是一个实习生提出来的,他问我这个问题,其实我也不会,就顺便查了查)。转发nginx,主要使用的是stream模块,就是新建一个和http模块同级的stream模块(不是在http模块里面)

1
2
3
4
5
6
7
8
9
10
11
12
stream {
  upstream backend {
    server 127.0.0.1:10001;
    server 127.0.0.1:10002;
  }
  server {
    listen 10000;
#    listen 10000 udp; 如需代理udp端口则在端口后面加udp即可
    proxy_timeout 20s;
    proxy_pass backend;
  }
}
参考文章:
1.Nginx 配置TCP代理转发 (这篇文章的配置,太繁琐了)
2.nginx配置tcp连接方案 (这里新建了一个py文件,就把我整蒙了,我估计他应该是写错了,应该是tcp.conf)
3.Nginx 配置TCP代理 (这里也是大同小异,就是多讲了upstream的轮换着进行代理)
4.Nginx 配置TCP代理 (最后的结论和上面的也差不多)

8.区分手机端还是PC端

pc端

1
2
3
4
5
6
7
8
9
server{
listen 80; # IPv4
server_name www.proheng.com;
## 移动端
if ($http_user_agent ~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
rewrite ^(.*) http://mb.proheng.com$1 permanent;
}
}

移动端

1
2
3
4
5
6
7
8
9
10
server{
listen 80; # IPv4
server_name mb.proheng.com;
#非移动端跳转到 www.one.com
if ($http_user_agent !~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
rewrite ^(.*) http://www.one.com$1 permanent;
}

}

参考文章:
1.Nginx区分PC或手机访问不同网站 (这里是使用了nginx和js结合的方式,更加的精确)
2.nginx判断手机端还是电脑 (这篇文章只是使用了nginx进行了判断)
3.nginx 移动端和pc端自动跳转 (这篇文章其实是通过rewrite进行了不同域名的跳转)

9.iframe配置

设置允许iframe 嵌套,X-Frame-Options 有可能的值:deny,sameorigin,allow-from。

  • DENY:表示该页面不允许在frame中展示,即便是在相同域名的页面中嵌套也不允许。
  • SAMEORIGIN:表示该页面可以在相同域名页面的frame中展示。
  • ALLOW-FROM url:表示该页面可以在指定来源的frame中展示。
  • ALLOWALL:表示该页面允许全部来源域名的frame展示。
1
2
3
4
5
## 如果 proxy_pass 已经返回了 X-Frame-Options,可以使用 proxy_hide_header 隐藏掉。
location / {
proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "ALLOW-FROM https://localhost:3000/" always;
}

我遇到的问题,就是我用上面的 add_header 进行了配置,浏览器总是提示我 :发现无效的 X-Frame-Options 头:“ALLOW-FROM https://localhost:3000/”指令无效。

【解决】
解决方法就是在nginx配置中,增加 Content-Security-Policy

1
2
3
4
5
6
7
## 如果 proxy_pass 已经返回了 X-Frame-Options,可以使用 proxy_hide_header 隐藏掉。
location /{
proxy_pass https://xxx;
proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "ALLOW-FROM localhost:3000" always;
add_header Content-Security-Policy "frame-ancestors localhost:8080 localhost:*";
}

后来设置之后,在浏览器中打开,控制台还是出现了问题:“Invalid ‘X-Frame-Options’ header encountered when loading ‘xx’: ‘ALLOW-FROM xxx, ALLOW-FROM xx’ is not a recognized directive. The header will be ignored.”

参考文章:
1.Nginx 允许 frame 嵌套 这篇文章有用,对X-Frame-Options几个取值都做了说明
2.nginx 代理突破iframe跨域限制
3.Nginx使用X-Frame-Options防止被iframe跨域 这里有proxy_hide_header和add_header X-Frame-Options 一起使用;
4.X-Frame-Options ALLOW-FROM 无效 谷歌浏览器较新版不支持ALLOW-FROM.用另一个响应头Content-Security-Policy代替,配置其中的frame-ancestors,并给了.Net的代码示例
5.X-Frame-Options Content-Security-Policy HTTP 头中的 frame-ancestors 指令会替代这个非标准的 header。CSP 的 frame-ancestors 会在 Gecko 4.0 中支持,但是并不会被所有浏览器支持。然而 X-Frame-Options 是个已广泛支持的非官方标准,可以和 CSP 结合使用。这里算是MSDN上的说明,还对Apache、nginx、IIS、HAProxy和 Express 不同的服务器做了说明。
6.nginx设置X-Frame-Options的两种方法 X-Frame-Options 有三个值:DENY、SAMEORIGIN、ALLOW-FROM uri。
7.iframe跨域安全 ALLOW-FROM指令在除IE以外的很多浏览器中无效,

10.去掉双斜杠

去除前:http://localhost//aa///bc 去除后:http://localhost/a/b/c

1
2
3
4
5
server {
//去除多斜杠的配置
merge_slashes off;
rewrite (.*)//(.*) $1/$2 permanent;
}

11。转发cookie

在使用 java 开发的时候,发现有些程序总是设置了 Set_Cookie 进行内容记录。

在Nginx中设置Cookie路径需要通过添加”add_header”指令。具体语法如下:

add_header Set-Cookie “cookie_name=cookie_value; path=/path; expires=date; domain=domain.com; secure; httponly”;

cookie_name: 定义Cookie的名称
cookie_value: 定义Cookie的值
path: 定义Cookie的路径,例如/path表示只在/path目录下生效
expires: 定义Cookie的过期时间,格式为:Wdy, DD-Mon-YYYY HH:MM:SS GMT
domain: 定义Cookie的作用域,例如domain.com表示只在domain.com下生效
secure: 表示只在HTTPS协议下传输
httponly: 表示禁止客户端脚本访问该Cookie

例如:add_header Set-Cookie “cookie_name=cookie_value; path=/path; expires=Thu, 28-May-2020 12:00:00 GMT; secure; httponly”;

还可以使用单项配置,比如 proxy_cookie_path 进行路径的设置。给一个例子,比如将 dxsrealtime 转发到 api 这个接口,在api这个接口中通过后台设置了 “Set-Cookie:JSESSIONID=3CA79D7AD3EDCFBA7393FD8FE4ED5C4E; Path=/api; HttpOnly”,那么接下来的 path ,为了能被浏览器识别,那么就需要进行转换。这里要说明的是:“如果这个 path 和浏览器地址栏的不一致, 浏览器会拒绝写入这个 cookie, 相当于登陆了个寂寞.” 修改方式如下:

1
2
3
4
location /dxsrealtime/ {
proxy_cookie_path /api /dxsrealtime;
proxy_pass http://xxx:65199/api/;
}
参考文章:
1.Set-Cookie 这里写了很多可以设置的属性,比如path。
2.Nginx反向代理理解误区之proxy_cookie_domain
3.nginx设置cookie path
4.Nginx 中 proxy_cookie_path 的用法 这篇文章倒是可以的,简单易懂的。
5.nginx设置cookie path 这里的参数说的很详细

问题

(1) 此Set-Cookie 未设置标头信息未制定 “SameSite” 属性,默认为 “SameSite=Lax”,并且已被屏蔽,因为它是一个跨网站请求,而该响应并不是对顶级导航操作的响应,此 Set-Cookie 必须在设置是指定 “SameSite = None” 才能跨网站使用。

当我在一个 iframe 网站中设置 Set-Cookie 的时候,后面的信息出现了黄色的叹号,说明已经被屏蔽了。

这里有两种方式,一种就是使用 proxy_cookie_flags,一种就是使用 more_set_headers 模块,但是这个模块需要安装,大部分的文章都是在linux下安装的,但是window下安装就会有问题。

【尝试方案】
(1)我尝试下载了 openresty-1.21.4.1-win64,然后配置了其中的 location 面的代码,增加了 more_set_headers 。

1
2
3
4
5
location /dxsrealtime/ {
proxy_pass http://xxx:65199/api/;
# 这里相当于改变了请求的头信息,这里我们在之前的set-cookie中追加了Secure,以及Samesit=None
more_set_headers 'Set-Cookie: $sent_http_set_cookie; Secure; SameSite=None';
}

结果没有报错,但是没有成功,后来我觉得之所以不成功,是因为没有完全重启全部的nginx进程。

1
taskkill /F /IM nginx.exe

(2) 我尝试使用:proxy_cookie_flags Secure Samesite=None; 配置,结果就是不支持。

【解决方案】
最后我重新回到了 nginx,进行配置,因为我域名本身就是 https 了,所以可以配置 secure; SameSite=none。可以将后端设置的 path=/api,全部改为 path=/

1
2
3
4
location /dxsrealtime/ {
proxy_pass http://xxx:65199/api/;
proxy_cookie_path /api "/; httponly; secure; SameSite=none";
}
参考文章:
1.Chrome 80 Cookie跨域 Samesite Lax 的错误
2.nginx添加Set-Cookie属性Secure和HttpOnly proxy_cookie_flags:为cookie设置一个或多个标志。该cookie可以包含文本,变量,以及它们的组合。的 secure, httponly, samesite=strict, samesite=lax, samesite=none 参数添加相应的标志。的 nosecure, nohttponly, nosamesite 参数移除对应的标志。(本来想用这个属性的,但是不知道为啥nginx识别不到proxy_cookie_flags属性。) 这里还有nginx增加headers_more模块参考。
3.nginx –增加 headers-more-nginx-module
4.nginx for windows –增加 headers-more-nginx-module模块 这个文章写的不好,跳到了一个 Openresty 模块的地方,也就说其实安装 Openresty 就已经集成了 more_set_headers模块
5.Windows版本如何添加more_set_headers和more_clear_headers模块
6.通过Nginx设置HttpOnly Secure SameSite参数解决Cookie跨域丢失 要通过nginx配置SameSite,可以在 nginx.conf 的 location 节点下进行配置proxy_cookie_path / “/; httponly; secure; SameSite=Lax”;
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。