Mystery0の小站

Mystery0の小站

Umami 嵌入到iframe中无法打开的问题记录

2023-11-28

问题表现

image-duhf.png

Refused to frame 'https://umami.mystery0.vip/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' undefined".

原因分析

经过大佬分析,是 umami 默认不允许嵌入到iframe中,在嵌入到iframe时,页面请求响应中有如下的Header信息:

Content-Security-Policy:
default-src 'self'; img-src *; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src 'self' api.umami.is; frame-ancestors 'self' undefined;

查阅 umami文档,看到这里有环境变量可以指定,用于控制嵌入到iframe时的表现

image-equc.png

不过不足的是,它是一个编译变量,仅在编译的时候生效,运行时是不生效的,代码如下:

image-ffzy.png

因为官方编译Docker镜像的时候,没有指定这个环境变量,所以自然就是 undefined

解决方案

知道原因之后,我们立即得出以下两个解决方案:

  1. 按照官方的方案,自己编译一个Docker镜像,在编译时指定 ALLOWED_FRAME_URLS
  2. 通过nginx或者openrest响应头直接改掉

方案1

这种办法适用于通过 vercel 等托管平台,因为一般这些托管平台都是将对应服务的源码下载下来,然后自己编译一次然后运行(也有一些平台是直接部署Docker镜像),给整个部署流程设置上环境变量之后,自然就相当于在编译过程中加上了官方需要我们手动指定的环境变量,最终结果就是满足我们预期的。

方案2

这种方案就是在不修改我们已经部署好的 umami 实例的基础上,通过外部的东西来将这个 Header 修改为我们期望的值,这样子虽然 umami 返回了 undefined ,浏览器拿到的却是 blog.xxx.com
写到这里,我们想到的就是通过 Nginx 或者 Openresty 来实现以下的内容:

  • 删除 umami 返回的 Content-Security-Policy
  • 加上我们期望的 Content-Security-Policy

我这里在 umami 外面部署使用的 openresty ,所以直接在反向代理上面配置这样两行内容就行了:

add_header Content-Security-Policy 'frame-ancestors blog.mystery0.vip';
proxy_hide_header 'Content-Security-Policy';

例如:

image-ixpo.png

Nginx 应该也有办法修改,只是我这边没有用,不确定上面的配置能不能生效。