当前位置: 首页 > article >正文

Nginx基础详解4(location模块、nginx跨域问题的解决、nginx防盗链的设计原理及应用、nginx模块化解剖)

续Nginx基础详解3(nginx.conf核心代码讲解、常用命令解析、Nginx日志切割)-CSDN博客

目录

10.location模块详解

10.1默认匹配规则‘ /’

10.2精确匹配规则‘=/’

10.3正则表达式‘~* \’

10.4精确正则匹配'~ \'

10.5路径匹配‘^~ /’

11.nginx中解决跨域问题

11.1何为跨域?

11.2Nginx是如何解决跨域问题的?

12.nginx防盗链的设置

12.1何为防盗链?

12.2Nginx是如何配置防盗链的?

13.nginx模块化设计解析

13.1从nginx的安装包来解析nginx


10.location模块详解

        location的本质是一种路径的匹配规则,谈到规则,就不得不说我们计算机中的匹配规则“正则表达式”了。而在 Nginx 中location 结合正则表达式可以完成路径匹配、参数捕获、重定向、访问限制、负载均衡、URL重写和缓存控制等多种功能。

10.1默认匹配规则‘ /’

        通过‘ /’来访问nginx的页面,通常这个页面是默认页面,或者使用' /路径'来进行访问其他的页面,前提是路径需要在服务器中存在。

10.2精确匹配规则‘=/’

        当你使用 location = / 时,你告诉 Nginx 只处理精确匹配根路径 / 的请求。这不会匹配任何额外的路径或文件名,只有完全的 / 请求才会被这个

location 块处理。

实验前先声明一下实验的路径结构:

/home

├── 屏幕截图 2024-08-07 093328.png

├── cat.gif

├── image.png

├── lichuanhua

└── image

        └── lvyou.jpg

        假设你有一个需求,当用户访问网站的根路径时,你想显示一个特定的 图片。你可以使用精确匹配来实现这一点:

注意:访问不到网页的原因如下:

        1.可能将root后面的目录也写上了,变成了ip:端口号/root/桌面/image.png,这样会弹出404的报错

        错误的原因就是混淆了root和location的作用root是告诉nginx从哪找,location是告诉用户需要的资源名称,用户直接输入资源名称nginx就会根据root后面的目录找这个目录下有没有这个资源。而如果真放在了root目录下但是没改root的访问权限,那么nginx虽然找到了但是进不去,因为权限问题可能会导致403的报错,所以还是建议大家别学我放到root目录这个行为,还是放到普通的一个目录下吧(例如/home)

        2.也可能是用户在浏览器中输入的路由和在nginx的配置文件中写的路径不一致,因为书写问题导致的找不到资源的404报错。

        3.想要访问别的图片但是用了上述的方法变成了404报错

        因为我们使用了精确匹配‘=/’,如果我们还想访问别的资源的话建议再写一个location,因为精确匹配在一个location下仅能输入正确的路由后找到一个资源。

完成后正常的样子如上。

10.3正则表达式‘~* \’

        正则表达式又是一个全新的知识点,确实该表达式不论是在shell编程、高级语言的开发等方面都占据了很重要的一部分,今天我仅讲涉及多的知识,让大家深入浅出的体验一把正则表达式的快乐(如果想完整的了解它建议去菜鸟教程-正则表达式这个网站学习哦

        对于‘~*’的理解:~表示我们就要使用正则表达式了,算是对使用正则的声明,*表示我们的正则表达式是不区分大小写的,在我讲的linux中曾经说过*就是代表通配符的意思,可以替代大写小写字母。

        示例:创建一个location路由,通过路由我们上传的在home目录下的jpg、gif、png这些类型的资源都可以进行访问。

        原理:只要是/home路径下的jpg、gif、png这类资源不论大小写都可以访问,nginx都会一层一层地映射到/home路径下。为什么说是一层一层呢?因为 Nginx 会递归地检查每个子目录,直到找到匹配的文件为止(结果如下,注意看地址栏信息,png格式的图片被匹配到了)。

同理,我们在home目录下有一张cat的GIF格式的文件咱们看看能不能匹配到(结果如下):

        我们发现如果输入cat.GIF路由会强制给你转换为gif并且没有找到对应的资源,但不是说~*是不区分大小写的吗?为什么还找不到呢?

        这就涉及到nginx的底层的内容了,我们前面强调nginx会一层一层的递归的查找资源,但是在home文件夹下它已经递归完了就是没有找到GIF格式的资源,所以我们最好的解决方式有:

        1.更改正则表达式的内容,将原先的location块的正则内容改为如下内容,使用更明确的正则表达式来确保所有大小写变体都被覆盖。

location ~* \.(gif|GIF|jpg|JPG|jpeg|JPEG|png|PNG)

        2.在相关的路由下(我这个实验是在home路径下)重新创建一个GIF大写格式的文件,因为linux系统是部分大小写的,这样nginx也可以找到大写的资源了,这种方法虽然是本办法,效率也不高,但是比较稳定。综上,我还是建议第一种解决方法,大不了改改规则也不至于重新创建一堆大写同名资源吧。。。。

做完的结果如下

10.4精确正则匹配'~ \'

        不同于上述的精确匹配仅能找到一个文件,精确正则匹配可以区分大小写的匹配到多个同类资源的文件。而精确正则匹配又和正则表达式匹配差了一个*,我们也可以从正则表达式的理解角度,抽离出*的含义,就是精确正则匹配的含义。

实验开始(如下图)

        因为是精确的正则匹配,我们的结果其实和10.3的结果差不多,输入cat.gif可以访问而输入cat.GIF则不在精确匹配行列中,Nginx递归不到,资源无法找到。

(无法找到的图片如下)

10.5路径匹配‘^~ /’

        路径匹配用一句话概括就是用户仅能访问到规定路径下的所有资源,如果不在规定的路径下都不可以进行访问。这样可以显示用户的可访问范围,保证我们的服务器资源安全。

        路径匹配是不使用正则表达式的,是另一种匹配方式,所以^表示“非”,而~表示正则表达式的声明,二者结合(^~)就是不使用正则,不使用它的话后面也不需要加具体的规则了,改为路径即可,root表示nginx从哪个根目录下开始找,/image表示nginx只能找根目录下的image文件内的资源。

结果如下

如果我们换了路径那么nginx绝对找不到

11.nginx中解决跨域问题

11.1何为跨域?

        现在有这样一种情况:用户们想要访问访问慕课网,所以浏览器输入慕课网的网址,慕课网网络服务器现在接收了大量的异步请求Ajex报文,而假设该客户端中又存在多个关于淘宝的链接,用户想要去淘宝又会从慕课网的客户端跳转到淘宝的网络服务器,而淘宝服务器同样接受了Ajex的异步请求,但是淘宝的这些异步请求可以接受吗?显然不能!因为慕课网的客户端和慕课网的网络服务器是在同一域中的,但是,从慕课网的客户端到淘宝显然是不在同一个域中的,这就出现了跨域的问题。这也是浏览器的安全保障,浏览器会限制ajex的请求报文在网络不同的域中乱跳(跨域请求)。

11.2Nginx是如何解决跨域问题的?

        可以通过“跨域资源共享”(CORS)的方法来解决跨域的问题。原理就是允许浏览器在当前的域名里面用JS的形式以异步的形式发送给不同的域名从不同的域名中获取相应的数据。

具体可以实现跨域的几个方法

1.Jsonp

<!DOCTYPE html>
<html>
<head>
    <title>JSONP Demo</title>
    <script>
        // 定义回调函数
        function handleResponse(response) {
            console.log('Data received:', response);
        }
        // 定义 JSONP 请求函数
        function jsonp(url, callback) {
            var script = document.createElement('script');
            script.src = url + '&callback=' + callback;
            document.body.appendChild(script);
        }

        // 调用 JSONP 请求
        jsonp('http://example.com/getData', 'handleResponse');
    </script>
</head>
<body>
    <h1>JSONP跨域请求示例</h1>
</body>
</html>

2.SpringBootCors

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @CrossOrigin(origins = "http://example.com") 
    @GetMapping("/endpoint")
    public String endpoint() {
        return "This is a cross-origin endpoint";
    }
}

全局 CORS 配置(Java 配置):

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://example.com")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
        };
    }
}

3.Nginx

​
server {

listen 80;

server_name example.com;

# 允许跨域请求所需的 HTTP 头

add_header 'Access-Control-Allow-Origin' '可以允许跨的域的域名';

add_header 'Access-Control-Allow-Credentials' 'true';

add_header 'Access-Control-Allow-Methods' '*';

add_header 'Access-Control-Allow-Headers' '*';

location / {

# 处理预检请求

if ($request_method = 'OPTIONS') {

return 204;

}

# 代理到后端服务器

proxy_pass http://localhost:8080;

}

}

​

        相比之下,只有nginx的配置是最少的,这也是为什么网络中常说的“同样的工作让计算机不同岗位的人去干,算法岗是论文,运维岗是诗”这句话,当然单凭这一个例子就说明这样的结论有点管中窥豹了,后续我也会用较多的例子来证明这句话的正确性。

当然,上述的语句不光可以放在server下,也可以放在location块内,二者还是又区分的。

放在 server 块内:

        当 add_header 指令放在 server 块内时,这些头部将被添加到服务器配置中的每个响应中。这意味着,无论请求的是哪个位置(location),这些 CORS 头部都会被发送。这种方法的好处是,你不需要在每个 location 块中重复这些指令,它们将全局应用到所有的响应上。

放在 location 块内:

        当 add_header 指令放在特定的 location 块内时,这些头部将只被添加到匹配该 location 的请求响应中。这允许你为不同的资源或路径设置不同的 CORS 策略。

看不明白?还是太官方?我先来解释一下相关的配置语句再来看吧!

Access-Control-Allow-Origin: '指定的允许跨域的域名'
        这个头部表示允许指定域对资源进行跨域请求。在开发阶段,使用 *(通配符)可以方便地允许所有域的跨域请求,但在生产环境中,出于安全考虑,建议明确指定允许的域(例如 http://example.com)。

Access-Control-Allow-Credentials: 'true'
        当设置为 true 时,表示允许浏览器发送跨域请求时带上认证信息(如 Cookies 或授权 headers)。这通常需要与 Access-Control-Allow-Origin 一起使用,并且不能设置为 *,必须指定明确的请求域。

Access-Control-Allow-Methods: '*'

        这个头部指定了哪些 HTTP 方法(如 GET、POST、PUT、DELETE 等)被允许用于跨域请求。使用 * 表示允许所有方法,但在实际应用中,最好明确指定所需的方法,以增强安全性。

Access-Control-Allow-Headers: '*'

        这个头部指定了服务器支持哪些自定义请求头部信息。使用 * 表示允许所有头部,但在实际应用中,最好明确指定所需的头部(如 Content-Type、Authorization 等)。

让我再来比喻让大家更清晰的明白这几个拗口的配置:

        可以把 Nginx 服务器想象成一个大型图书馆,而 location 块就像是图书馆内不同的区域(如科技书籍区、历史书籍区等)。每个区域有不同的规则和设置(比如某些区域允许拍照,某些区域不允许)。

        科技书籍区:可能允许拍照,这就像允许跨域请求的资源。在 Nginx 中,这通过在相应的 location 块中设置 CORS 头部来实现。

        历史书籍区:可能不允许拍照,这相当于不需要跨域访问的资源。在 Nginx 中,这个区域的 location 块就不会包含 CORS 头部。

        当访客(HTTP 请求)进入图书馆(Nginx 服务器)时,他们会根据所在的区域(URI 路径)遵守不同的规则(location 块中的配置)。图书馆管理员(服务器管理员)可以根据需要在不同区域设置不同的规则,以确保秩序和安全。

12.nginx防盗链的设置

12.1何为防盗链?

        防盗链技术主要是用来防止其他网站未经授权直接引用你的资源,从而保护你的带宽和服务器资源不被滥用。它通过检查 HTTP 请求的Referer 头部(注意:这里的 "Referer" 是一个常见的拼写错误,但已经成为标准)来实现,确保请求来自允许的来源。

12.2Nginx是如何配置防盗链的?

        假设你手里现在有一台云服务器并且已经配置好了,但是你网站的内的资源片却是每分钟都在计费,假设你没有配置防盗链,别人的服务器想要引用你的网站就可以不用缴费,从而让你的服务器计费更加严重,相当于盗窃(盗窃你的流量、版权、服务器资源、网络性能和广告费等),那该如何防止这些服务器滥用你的服务器内的热链接进行盗窃呢?在nginx反向代理服务器就可以解决这一问题。

配置方法(在server块内且在location块外进行配置防盗链):

valid referers *.网址主机名;(例如valid referers *.123.com)

if($invalid referer){

return 404;

}

代码解释:

  1. valid referers *.网址域名;
    1. 检查 Referer 头部:通过检查 HTTP 请求的 Referer 头部来确定请求是否来自合法的源。如果我们头部的请求域名和我们配置的*.网址域名相同那么该请求就是合法的,可以访问资源
  2. if($invalid referer){
    1. Nginx 的 valid_referers 指令可以帮助您定义哪些引用是有效的。调用nginx的环境变量,表示原站点发来的不合法的请求报头,那么如果if条件成立,则返回404资源丢失网页,这样外部不合法的、验证未通过的报头只会得到404的页面而不可以大摇大摆的进到服务器内盗窃链接等资源。
  3. return 404;
    1. 取消请求,返回404页面,从而实现防盗链功能。也可以返回其他网页(这个网页是我们自己写的提示错误的网页,但是多一事不如少一事,具体的方法如下)

server {

listen 80;

server_name example.com;

# 定义自定义错误页面

error_page 403 /custom_403.html;

error_page 404 /custom_404.html;

# 用于防盗链的 location 块

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {

valid_referers none blocked server_names example.com *.example.com;

if ($valid_referers != ok) {

return 403;

}

}

# 放置您的自定义错误页面的路径

location = /custom_403.html {

root /path/to/your/html;

}

location = /custom_404.html {

root /path/to/your/html;

}

}

13.nginx模块化设计解析

上图的解释为:

  • Nginx Core:Nginx 核心模块,负责基础的网络通信和事件处理,同时还可以协调其他模块的运作。
  • Event Module:事件模块,处理网络连接的接收和数据的读写事件。
  • Http:HTTP 模块,处理 HTTP 协议的请求和响应。
  • Phase Handler:阶段处理器,HTTP 请求处理的不同阶段,包括服务器解析、转发、内容生成等。
  • Output Filter:输出过滤器,负责响应数据的发送和缓存。
  • Upstream:上游服务器,Nginx 可以配置多个上游服务器来进行负载均衡。
  • Mail:邮件模块,处理邮件代理的功能。
  • Load Balancer:负载均衡器,Nginx 可以作为负载均衡器分配请求到多个后端服务器。
  • Extend Module:扩展模块,指 Nginx 可以添加的第三方模块来扩展其功能。

Nginx 的模块化处理流程:

1.客户端请求:客户端发起请求到 Nginx 服务器。

2.Event Module:Nginx 的事件模块接收请求并将其注册为事件。

3.Http Module:HTTP 模块处理 HTTP 请求,包括解析请求行、请求头等。

4.Phase Handler:请求处理的各个阶段,例如:

  •         Server_rewrite:服务器级别的重写。
  •         Location rewrite:位置级别的重写。
  •         Proxy pass:代理传递。
  •         Static file:静态文件处理。
  •         Error page:错误页面处理。

5.Upstream:如果请求被代理,Nginx 会根据配置的 upstream 组来选择一个后端服务器。

6.Load Balancer:Nginx 作为负载均衡器,将请求分发到不同的上游服务器。

7.Output Filter:输出过滤器处理响应数据,并将其发送回客户端,包括gzip的压缩也是在这里声明的。

8.Mail Module:如果处理的是邮件相关的请求,邮件模块会介入处理。

9.Extend Module:第三方扩展模块可能会在请求处理的任何阶段介入。

模块化的好处:

  • 灵活性:可以根据需要添加或删除模块。
  • 性能:模块化设计使得 Nginx 可以高效地处理请求。
  • 可扩展性:第三方模块可以添加新的功能。

通过这种模块化设计,Nginx 能够灵活地处理各种类型的请求,并提供高性能和高可用性的服务。

13.1从nginx的安装包来解析nginx

        我们回到nginx的安装目录下(还是那句话,安装目录和运行的生成目录位置是不同的,生成的目录一般存在于/usr/local/nginx下,安装的目录位置多样,我现在这台机器是装在了/root目录下)我们cd到nginx的安装位置(不是在安装包内而是在解压完成的软件内!如下图)

        我们发现nginx有许多目录,我们之前在做配置安装的时候重实践,并没有说具体哪个文件夹是干什么的,我们现在就可以具体的来聊聊。

auto:auto在英语中表示自动的意思,而在此,nginx会根据auto目录内的文件,自动的识别操作系统的版本、内核,以及如何进行编译,参照的编译脚本等都存在于auto目录内,也是auto目录内的文件进行识别的。

CHANGES:表示显示历史的版本号,这里我就不截屏了,基本用不到,相当于一个版本的解释器。

CHANGES.ru:俄语版的CHANGES,因为nginx是俄罗斯开发的

conf:nginx所有的配置文件都存放在该目录下,而核心的配置文件叫做nginx.conf

configure:configure 是一个用于初始化软件包编译过程的脚本,它自动检测系统环境并生成适合该环境的 Makefile。这个脚本是编译配置过程中非常关键的一步,它确保了软件能够在不同操作系统和硬件平台上正确编译和安装。

contrib:contrib 目录通常包含了一些额外的、非核心的脚本、工具或示例代码,这些内容由项目的贡献者提供。这些资源可能用于增强项目功能、提供额外的集成选项或帮助用户更好地理解和使用项目。contrib 目录中的内容通常不是项目的主要部分,但它们可以为用户提供额外的便利和支持。

html:默认存放静态资源的文件目录

LICENSE:英文中认证的意思,也是一个说明文件,nginx的相关说明和协议文件等存放在此。

Makefile:编译完成之后的相应的文件存放的位置,大家还记得最开始我们安装nginx的make文件吗?就是在那个时候被创建出来的

man:nginx的手册

objs:第三方的插件、模块;后期我们学习到轮询、ip_hash的时候以及集群的时候还会和它打交道的。

README:“读我”的意思,是nginx的作者写的“说明书”。“具体的细节去官网查看”(这是他说的不是我说的,我只负责里面文件内容的翻译。。。)

src:nginx配置的源码,很多很长,建议C语言不好的玩家不要随意操作,我们要看就用cat或者more命令看看就好了,不要随便改!!!


http://www.kler.cn/a/328609.html

相关文章:

  • Siglus引擎 Unpack | 未完待续
  • 如何在C#中处理必盈接口返回的股票数据?
  • 5G的SUCI、SUPI、5G-GUTI使用场景及关系
  • 机器学习基础04
  • 【含开题报告+文档+PPT+源码】基于springboot的教师评价系统的设计与实现
  • React Native 全栈开发实战班 - 数据管理与状态之Zustand应用
  • Vue.js 组件开发
  • 【数据库】 MongoDB 查看当前用户的角色和权限
  • C++八股进阶
  • 【API安全】crAPI靶场全解
  • (void*) 是啥意思
  • 【Vue】为什么 Vue 不使用 React 的分片更新?
  • 重置linux后vscode无法再次使用ssh连接
  • C# HttpClient请求URL重定向后丢失Authorization认证头
  • 基于RustDesk自建远程桌面服务
  • 0基础学前端 day9--css布局
  • UI设计师面试整理-团队合作与沟通能力
  • 深度学习·wandb
  • 自然语言处理问答系统技术
  • html5 + css3(下)
  • STL容器适配器
  • OpenCV 形态学相关函数详解及用法示例
  • 字符串逆序
  • 滚雪球学MySQL[3.3讲]:MySQL复杂查询详解:CASE语句、自连接与视图管理
  • OpenCV视频I/O(11)视频采集类VideoCapture之设置视频捕获设备的属性函数 set()的使用
  • Go语言入门:掌握基础语法与核心概念