WebView2 中的新 Sec-* headers

New Sec-* headers in WebView2

在 C++ 中使用 MS WebView2,如果访问 https://manytools.org/http-html-text/http-request-headers/

,我可以看到许多“Sec-*”-headers

举几个例子:

Sec-Fetch-Dest document
Sec-Fetch-User ?1
Sec-Fetch-Mode navigate
Sec-Fetch-Site none
Sec-Ch-Ua-Mobile ?0
Sec-Ch-Ua "Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100", "Microsoft Edge WebView2";v="100"

这些新的 headers 在 https://wicg.github.io/ua-client-hints/

中提到

有什么方法可以 access/edit 那些 headers,最好是在 C++ 中?

可以使用命令行选项禁用 Sec-Ch headers:

--disable-features=UserAgentClientHint

并从 C++ 执行此操作:

Microsoft::WRL::ComPtr<CoreWebView2EnvironmentOptions> options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
options->put_AdditionalBrowserArguments(L"--disable-features=UserAgentClientHint");

但是,我希望能够编辑这些值。

进一步的谷歌搜索显示了这个页面,我猜它回答了这个 post: https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name

你说得对 sec-* header 是“禁止 header”列表的一部分。但是它们被禁止用于客户端代码,例如在 user-agent 上运行的 JS。但是 user-agent 浏览器可以设置这些字段。

您可以更改添加到 add_WebResourceRequested 的回调中的某些 sec-* header。一些字段如 Sec-Fetch-Site 之后会被覆盖,其他字段如 Sec-Fetch-Mode 可以设置,但不能删除,因为如果在 WebResourceRequestedEvent 之后未设置,它们将获得默认值。但是您可以像这样更改大多数 sec-ch

注意:这段代码只是为了演示方法,它缺少一堆错误处理

EventRegistrationToken webResourceRequestedToken;
webviewWindow->AddWebResourceRequestedFilter(L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL);
webviewWindow->add_WebResourceRequested(
  Callback<ICoreWebView2WebResourceRequestedEventHandler>([](ICoreWebView2* sender,
                                                             ICoreWebView2WebResourceRequestedEventArgs* args) {
    COREWEBVIEW2_WEB_RESOURCE_CONTEXT resourceContext;
    args->get_ResourceContext(&resourceContext);
    ICoreWebView2WebResourceRequest* req = nullptr;
    ICoreWebView2HttpRequestHeaders* headers = nullptr;
    ICoreWebView2HttpHeadersCollectionIterator* iter = nullptr;
    args->get_Request(&req);
    req->get_Headers(&headers);
    headers->GetIterator(&iter);
    BOOL hasCurrent = FALSE;
    iter->get_HasCurrentHeader(&hasCurrent);
    std::vector<std::wstring> headersToDelete;
    std::wstring secChPrefix = L"sec-ch";
    while (hasCurrent) {
      LPWSTR name = nullptr, value = nullptr;
      iter->GetCurrentHeader(&name, &value);
      if (secChPrefix.compare(0, secChPrefix.size(), name, secChPrefix.size()) == 0) {
        headersToDelete.push_back(name);
      }
      iter->MoveNext(&hasCurrent);
    }
    for (auto header : headersToDelete) {
      headers->RemoveHeader(header.c_str());
    }
    // Setting "Sec-Fetch-Site" will have no effect, will get overwritten afterwards
    headers->SetHeader(L"Sec-Fetch-Site", L"same-origin");
    // This will work, but removing this key will just make it take the default value
    headers->SetHeader(L"Sec-Fetch-Mode", L"same-origin");

    return S_OK;
  }).Get(),
  &webResourceRequestedToken);