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