节点 Http 模块和 IIS - 设置安全 Cookie

Node Http Module & IIS - Setting Secure Cookie

我的目标是在 IIS 的节点应用程序中使用安全标记的 cookie。

我正在开发 Next.js 应用程序,并且还尝试在 IIS 上进行部署以满足一些公司要求。我已经通过安装 iisnode、URL 重写模块、nodejs 到服务器来配置 IIS,并且主要遵循 this 视频中的步骤。

SSR 和静态结构运行良好。 IIS 已经有自己的 SSL 证书。根据我的研究;

iisnode requests from IIS to your node app running express. The ssl connection is terminated at IIS and your node app receives an http request. When the app requires cookies over a secure connection it fails.

因此,当涉及到带有安全选项的 cookie 时,这会产生问题。据我了解,我需要告诉节点服务器信任代理。我在 express 中找到了一种方法,但我想继续使用节点 http 模块,我认为必须有一种方法,因为 Express 只是在 http 模块之上制作的。不幸的是,与 this Express 示例不同,我找不到任何关于它的资源。

参考这个article在重写规则中设置cookie

<rewrite>
<outboundRules> 
    <rule name="Ensure secure Cookies" preCondition="Missing secure cookie">
        <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
        <action type="Rewrite" value="{R:0}; secure" />
    </rule>
    <preConditions>
        <preCondition name="Missing secure cookie">
            <!-- Don't remove the first line here, it does do stuff! -->
            <add input="{RESPONSE_Set_Cookie}" pattern="." />
            <add input="{RESPONSE_Set_Cookie}" pattern="; secure" negate="true" />
        </preCondition>
    </preconditions>
</outboundRules>

我不是节点专家。但是IIS url rewrite 可以使rewritten url 也是https。在这种情况下,我认为node app收到http请求的可能性很小。

我通过创建另一个用 express 构建的自定义服务器文件找到了我的解决方案。实际上,正如我提到的,从一开始我就知道有一种方法可以通过 express server 实现信任代理设置。但是因为我已经在使用 node http 模块,所以我不想改变这个结构,而是想了解如何在这个模块中完成这个代理设置。我找不到方法,但因为我知道 express.js 是建立在节点 http 模块上的;必须有办法。

不幸的是,要么我找不到它,要么很难实现然后表达 js。我已经有一个带有 http 模块的开发服务器,它还读取 ssl 证书等。我没有完全删除它,而是添加了另一个具有 expressjs 和代理设置的文件。

以下代码没什么大不了的,但可能对某些人有所帮助,因为它们提供了自定义 Next.js 服务器,这些服务器具有用于开发和代理服务器生产的 SSL 环境。

带有 express 和代理的服务器

// This server file intended to use behind IIS.
const next = require("next");
const express = require('express')
const port = process.env.PORT || 3000;
const app = next({ dev: false, dir: ".", quiet: false });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();
  server.set('trust proxy', 1)

  server.get("*", (req, res) => {
    return handle(req, res);
  });

  server.listen(port, (err) => {
    if (err) {
      throw err;
    } else {
      console.log(`Server started at port ${port}`);
    }
  });
});

server.dev

console.log("Development mode.");
const { createServer } = require("https");
const { parse } = require("url");
const next = require("next");
const fs = require("fs");

const port = process.env.PORT || 3000;
const app = next({ dev: devMode, dir: ".", quiet: false });
const handle = app.getRequestHandler();

const httpsOptions = {
  key: fs.readFileSync("./certs/cert.key"),
  cert: fs.readFileSync("./certs/cert.pem"),
};

app.prepare().then(() => {
  createServer(httpsOptions, (req, res) => {
    // Be sure to pass `true` as the second argument to `url.parse`.
    // This tells it to parse the query portion of the URL.
    const parsedUrl = parse(req.url, true);
    const { pathname, query } = parsedUrl;
    handle(req, res, parsedUrl);
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(`Port: ${port}`);
  });
});