iframe 引发的前端跨域问题总结
一. 场景再现
想把第三方网站通过 iframe 的方式嵌入到我网站里面,但是报错 blocked ,下面是详细复现步骤。
1.1 旧的网站
我有一个网站 http://127.0.0.1:2000 ,网站代码如下:
from http.server import HTTPServer, BaseHTTPRequestHandler
response_content = """
<!DOCTYPE html>
<html>
<head>
</head>
<body>
i am http://127.0.0.1:2000/
</body>
</html>
"""
class MyRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.send_header('X-Frame-Options', 'SAMEORIGIN')
self.send_header('Content-Security-Policy', 'frame-ancestors self')
self.end_headers()
self.wfile.write(response_content.encode('utf-8'))
if __name__ == '__main__':
server_address = ('', 2000)
httpd = HTTPServer(server_address, MyRequestHandler)
httpd.serve_forever()
运行网站 python3 server1.py
后查看浏览器,能正常访问:
1.2 新的网站
此时有了一个新网站 http://127.0.0.1:3000,代码如下:
from http.server import HTTPServer, BaseHTTPRequestHandler
response_content = """
<!DOCTYPE html>
<html>
<head>
</head>
<body>
i am http://127.0.0.1:3000/
</body>
</html>
"""
class MyRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.send_header('X-Frame-Options', 'SAMEORIGIN')
self.send_header('Content-Security-Policy', 'frame-ancestors self')
self.end_headers()
self.wfile.write(response_content.encode('utf-8'))
if __name__ == '__main__':
server_address = ('', 3000)
httpd = HTTPServer(server_address, MyRequestHandler)
httpd.serve_forever()
运行网站 python3 server2.py
后查看浏览器,能正常访问:
1.3 实现需求
现在我想在我旧的网站(2000端口)上嵌入这个新的网站(3000端口),我使用 iframe 来实现,修改 server1.py 的 response_content
部分的代码如下:
response_content = """
<!DOCTYPE html>
<html>
<head>
</head>
<body>
i am http://127.0.0.1:2000/
<div id="myiframe" style="height: 200px; width: 500px;">
<iframe src="http://127.0.0.1:3000" height="100%" width="100%">
</iframe>
</div>
</body>
</html>
"""
然后重新运行 python server1.py
服务,浏览器访问 http://127.0.0.1:2000/,得到了如下的错误,这是为什么呢?
二. 网站同源
网站为了安全考虑,避免别人把自己的网站嵌入到其他的网站上,往往会设置不允许非同源网站共享。
同源:表示当前网站的 协议、主机名、端口
都完全相同,表示同一个源,在同源的链接是可以任意访问的,因为你自己都不相信自己,谁还会相信你呢?
跨域:不是同源的两个地址,在某一个地址里面访问另外一个地址的时候就会产生跨域,就像前面的例子,2000端口和3000端口是两个完全不同的网站,3000端口不想被嵌入到其他网站上面去,所以设置了跨域请求限制。
如果不想别入嵌入自己的网站,可以设置跨域请求限制:
# 只与同源网站共享
self.send_header('X-Frame-Options', 'SAMEORIGIN')
# 不允许其他源共享,只有自己
self.send_header('Content-Security-Policy', 'frame-ancestors self')
三. 解决办法
前面的问题,只需要在 3000 端口修改响应 header 如下
# 与任意源共享
self.send_header('Access-Control-Allow-Origin', '*')
# 除了自己,还与 http://127.0.0.1:2000 共享
self.send_header('Content-Security-Policy', 'frame-ancestors self http://127.0.0.1:2000')
重启 python3 server2.py
查看浏览器:
所以,如果想通过 iframe 嵌入别人的网站,需要征得别人的同意才行~