头盔(Helmet)Express 显示 ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200。

8

请帮我,我在谷歌上找了很久也没有得到真正的答案来解决我的问题。 我想使用Helmet来保护我的Express服务器。但是当我使用它时,我会遇到这个错误:ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 200,用于从我的数据库加载图片。 这是我的Express服务器:

// Initialize server
const app = express()
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(cookieParser());
app.use(cors())
app.use(helmet())

// CORS configuration
app.use(function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

我从数据库中获取我的图片,所以本地主机的URL为:http://localhost:3000/image/<name_image>

如果我不使用头盔(helmet)一切正常。

请给予任何帮助。

6个回答

23

简而言之:禁用Helmet v5默认开启的Cross-Origin-Embedder-Policy头部

app.use(
  helmet({
    crossOriginEmbedderPolicy: false,
    // ...
  })
);

我是一个有用的助手,可以进行文本翻译。

我是Helmet的维护者。

Helmet将Cross-Origin-Embedder-Policy HTTP响应头设置为require-corp

设置此标头意味着加载跨域资源(例如来自另一个资源的图像)会更加棘手。例如,像这样加载跨域资源...

<img alt="My picture" src="https://example.com/image.png">

除非example.com显式允许,否则此方法将无效,需要通过设置一些响应头来实现。您的浏览器将尝试加载example.com/image.png,如果没有得到明确允许,则浏览器会放弃响应。

要解决此问题,您可以防止Helmet设置Cross-Origin-Embedder-Policy标头,如下所示:

app.use(
  helmet({
    crossOriginEmbedderPolicy: false,
    // ...
  })
);

我制作了一个小的示例应用程序,您可以使用它来玩耍。在我的测试中,它似乎不适用于HTTP,但在HTTPS上是有效的,这可能解释了为什么事情只在生产环境中出错。

1
我尝试了上述解决方法,但仍然出现相同的错误。 - shellakkshellu
2
在 React 应用中,如果您不将 crossorigin="true" 添加到 img 标签中,则它将无法正常工作。 - Hakim Asa
我添加了这个标志,但我仍然需要在嵌入的图像上使用“crossorigin”标签才能访问。我不想这样做。如何使它在不需要该标签的情况下工作? - Mote Zart
在ReactJS应用程序中,@MoteZart的答案对我有用。谢谢。 - Luccin
1
@HakimAsa - 你真的应该得到某种奖励!! - Alan Spurlock
显示剩余2条评论

6

我也遇到了同样的问题,这个方法解决了它:

helmet({
    crossOriginResourcePolicy: false,
})

FYI,这对我没有起作用,我不得不使用被接受的答案中的解决方案 crossOriginEmbedderPolicy: false,请参见:https://github.com/helmetjs/helmet/issues/343#issuecomment-1006259994。 - user1063287
将其包装在 app.use() 中。 - Promise Ihunna

2
如果版本控制对您来说是更好的选择,我在 helmet 的版本 >=5.0.0 上遇到了同样的问题。降级到 4.6.0 可以解决这个错误。

1

在我的情况下,我使用了那种方式

    helmet({
      crossOriginResourcePolicy: false,
    })

问题出在跨域资源策略上,应该与浏览器视为另一个来源的同一站点。

FYI,这对我没有起作用,我不得不使用被接受的答案中的解决方案 crossOriginEmbedderPolicy: false,请参见:https://github.com/helmetjs/helmet/issues/343#issuecomment-1006259994。 - user1063287

1

在谷歌上长时间搜索后,我从这里找到了解决方案:https://github.com/helmetjs/helmet/issues/176。我添加了这行代码:

res.setHeader('Cross-Origin-Resource-Policy', 'same-site');

只需要刷新并清除缓存(在MAC上使用cmd + R,在其他设备上使用ctrl + R),就可以完美解决问题。

感谢Evan Hahn


0

我搜了很多,但上面的解决方案都不适用于我,可惜。但最终,我找到了这个解决方案:

// Helmet for the security
server.use(helmet());

// Static File Serving Access for Uploads
server.use("/uploads",
    express.static(path.join(env.UPLOADS_BASE_PATH, "uploads"), {
    setHeaders: (res) => {
      res.setHeader("Access-Control-Allow-Origin", env.CLIENT_URL);
    },
  }),
);

// Cors Origin for Client Access
const corsOptions = {
  origin: env.CLIENT_URL,
  methods: ["GET", "POST", "PUT", "DELETE"],
  allowedHeaders: ["Content-Type", "Authorization"],
  credentials: true,
  optionsSuccessStatus: 200,
};

server.use(cors(corsOptions));

只需更改env.UPLOADS_BASE_PATHenv.CLIENT_URL变量以及“uploads”路由以符合您的喜好。似乎路由设置未被正确应用。通过此更新,确保为静态文件响应设置了Access-Control-Allow-Origin头信息。(服务器是Express。)

我希望这也能帮助别人。祝好运。

附言:最重要的部分是为我的静态路由设置头信息。Cors选项可以比那更简单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接