在节点应用程序中自行提交表单

Self submitting form in a node application

您好,我正在使用 node-oidc-provider

实现 SSO 客户端

背景:

node-oidc-provider 有一个内置的表单提交,要求用户通过单击一个按钮来“确认他想退出”,该按钮提交一个将撤销他的 OAuth 令牌的隐藏表单。

我想通过在页面加载时自行提交表单来跳过确认步骤,就像包作者建议的那样here

问题:

我已将随机数添加到脚本和元标记中,但浏览器仍然拒绝加载我的脚本

async function getNonce () {
  const crypto = require("crypto");
  return crypto.randomBytes(16).toString("base64");
}

async function logoutSource (ctx, form) {
  // @param ctx - koa request context

 const nonce = await getNonce();

 ctx.body = `<!DOCTYPE HTML>
   <head>
     <title>Logout</title>
     <meta http-equiv="content-security-policy"
      content="
        script-src 'nonce-${nonce}' strict-dynamic 'unsafe-inline';
        default-src 'self';
     ">
   </head>
   <body>
     ${form}
     <script nonce="${nonce}">
       var form = document.forms[0];
       var input = document.createElement('input');
       input.type = 'hidden';
       input.name = 'logout';
       input.value = 'yes';

       form.appendChild(input);
       form.submit();
     </script>
   </body>
 </html>`;

查看浏览器网络选项卡中的请求,我看到了 nonce

然而,当浏览器呈现响应时,nonce 因 CSP 违规而被删除,我猜元头有问题但在阅读 CSP 文档后我无法找出错误

更新 1 Chrome 显示此错误消息

火狐:Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).

您似乎同时发布了两个 CSP - 第一个通过 HTTP header,第二个通过元标记。
在这种情况下,所有来源都应该通过两个未被划伤的 CSP 才能被允许,但第一个 CSP 没有 nonce.
据推测,第一个 CSP 是由 Helmet 中间件发布的默认 CSP,它在 NodeJS 的依赖项中。

检查 HTTP 响应 header,手册为 here

如果 Content-Security-Policy HTTP header 存在,您有 2 个选择:

  • nonce 添加到 HTTP header 并删除元标记 CSP。
  • 在 HTTP header 中禁用 CSP 并使用元标记。

如果这是 Helmet 的技巧,那么可以使用以下方法关闭 CSP:

// This disables the `contentSecurityPolicy` middleware but keeps the rest.
app.use(
  helmet({
    contentSecurityPolicy: false,
  })
);