已复制
全屏展示
复制代码

iframe 引发的前端跨域问题总结


· 4 min read

一. 场景再现

想把第三方网站通过 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/,得到了如下的错误,这是为什么呢?

iframe无法嵌入

二. 网站同源

网站为了安全考虑,避免别人把自己的网站嵌入到其他的网站上,往往会设置不允许非同源网站共享。

同源:表示当前网站的 协议、主机名、端口 都完全相同,表示同一个源,在同源的链接是可以任意访问的,因为你自己都不相信自己,谁还会相信你呢?

跨域:不是同源的两个地址,在某一个地址里面访问另外一个地址的时候就会产生跨域,就像前面的例子,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嵌入三方网站成功

所以,如果想通过 iframe 嵌入别人的网站,需要征得别人的同意才行~

🔗

文章推荐