Web服务器-Nginx解决跨域问题

作者介绍:简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

图片

我们上一大章介绍了Kubernetes的知识,本章节我们进入中间件的讲解,这里会包含很多不同的类型组件,中间件的第一个大类我这里定义的是Web服务器。由于目前使用最广泛的Web服务器是Nginx,所以我们这里的讲解主要以Nginx服务器为主。

跨域介绍

跨域(Cross-Origin Resource Sharing,简称CORS)是指在一个域下的网页尝试请求另一个域下的资源时发生的情况。这里的“域”是指协议(如HTTP或HTTPS)、域名(如example.com)和端口号(如80或443)的组合。

在Web开发中,同源策略(Same-Origin Policy)是一种重要的安全措施,它限制了从一个源加载的文档或脚本如何与另一个源的资源进行交互。这个策略可以防止恶意网站读取另一个网站的数据,但它也限制了合法跨域请求的能力。

原始域

目标域

协议

端口

是否跨域

原因

a.com

a.com

HTTP

80

域名、协议、端口都相同

a.com

a.com

HTTPS

443

域名、协议、端口都相同

a.com

b.com

HTTP

80

域名不同

a.com

a.com

HTTP

8080

端口不同

a.com

a.com

HTTPS

80

协议不同

构建跨域

1.构建一个后端服务

用Python启动一个Web服务,监听在8000端口。

from http.server import BaseHTTPRequestHandler, HTTPServer

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        response = {'message': 'Hello, world!'}
        self.wfile.write(str(response).encode())

def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    print("Server started at localhost:8000")
    httpd.serve_forever()

if __name__ == '__main__':
    run()

2.使用静态网页去访问这个接口

通过Nginx配置,让我可以访问到这个页面,然后页面有一个连接点击会去请求通过Nginx转发的服务后端服务。​​​​​​​

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Frontend</title>
</head>
<body>
    <h1>My Simple Static Web Page</h1>
    <button id="loadData">Load Data from Backend</button>
    <div id="data"></div>

    <script>
        document.getElementById('loadData').addEventListener('click', function() {
            fetch('https://chenhong.fun/api')
                .then(response => response.json())
                .then(data => {
                    document.getElementById('data').textContent = data.message;
                })
                .catch(error => console.error('Error:', error));
        });
    </script>
</body>
</html>

Nginx配置了静态网页和一个api接口(转接到后端服务)。​​​​​​​

 location / {
        root /home/static;
        index index.html;
    }
    location /api {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        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;
    }

3.访问触发跨越

这里我们复用了前面的https配置,为了触发跨域,所以我这里使用IP访问。

当前域:IP

目标域:域名

图片

我这个是简单请求,所以后端会收到请求但是浏览器不会响应数据,在某些复杂的请求里面,请求都不会转发到后端,因为浏览器跨域保护,导致请求未向后端转发。

在调试里面的Console里面也会有跨域提示。

图片

4.修改Nginx配置

通过调整Nginx配置解决跨域问题。​​​​​​​

    location /api {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        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 'Access-Control-Allow-Origin' '*' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization' always;
        if ($request_method = 'OPTIONS') {
           return 204;
        }

重载Nginx以后,再重新通过IP访问,后端接口使用域名就不会触发跨域问题。

5.从后端代码层面界面解决跨域问题

就是不修改Nginx配置,而直接从后端来代码来实现,代码改成这样,则不会有跨域提示。​​​​​​​

from http.server import BaseHTTPRequestHandler, HTTPServer
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()
        response = {'message': 'Hello, world!'}
        self.wfile.write(str(response).encode())
    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
        self.end_headers()
def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    print("Server started at localhost:8000")
    httpd.serve_forever()
if __name__ == '__main__':
    run()

图片

运维小路

一个不会开发的运维!一个要学开发的运维!一个学不会开发的运维!欢迎大家骚扰的运维!

关注微信公众号《运维小路》获取更多内容。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值