通过 node-http-proxy 持久化基于 cookie 的会话

Posted

技术标签:

【中文标题】通过 node-http-proxy 持久化基于 cookie 的会话【英文标题】:Persisting a cookie based session over node-http-proxy 【发布时间】:2012-05-04 16:21:48 【问题描述】:

我有一个简单的基于 Express 的 Node.js Web 服务器,用于开发 javascript 应用程序。我将服务器设置为使用 node-http-proxy 来代理应用程序向在不同域和端口上运行的 Jetty 服务器发出的 API 请求。在我开始遇到会话管理问题之前,此设置一直运行良好。

在认证后,应用服务器返回一个带有认证令牌的 cookie,代表服务器会话。当我从我的文件系统 (file://) 运行 JS 应用程序时,我可以看到一旦客户端收到 cookie,它就会在所有后续 API 请求中发送。当我在节点服务器上运行 JS 应用程序并通过 node-http-proxy (RoutingProxy) 代理 API 调用时,请求标头从不包含 cookie。

我需要手动处理一些事情以通过代理支持这种类型的会话持久性吗?我一直在研究 node-http-proxy 代码,但这有点过头了,因为我是 Node 新手。

https://gist.github.com/2475547 或:

var express = require('express'),
    routingProxy = require('http-proxy').RoutingProxy(),
    app = express.createServer();

var apiVersion = 1.0,
    apiHost = my.host.com,
    apiPort = 8080;

function apiProxy(pattern, host, port) 
    return function(req, res, next) 
        if (req.url.match(pattern)) 
            routingProxy.proxyRequest(req, res, host: host, port: port);
         else 
            next();
        
    


app.configure(function () 
    // API proxy middleware
    app.use(apiProxy(new RegExp('\/' + apiVersion + '\/.*'), apiHost, apiPort));

    // Static content middleware
    app.use(express.methodOverride());
    app.use(express.bodyParser());
    app.use(express.static(__dirname));
    app.use(express.errorHandler(
        dumpExceptions: true, 
        showStack: true
    ));
    app.use(app.router);
);

app.listen(3000);

【问题讨论】:

【参考方案1】:

我通过手动查看响应来完成您的要求,查看它是否是 set-cookie,剪掉 JSESSSIONID,将其存储在变量中,并将其作为标头传递给所有后续请求。这样反向代理就充当了 cookie。

on('proxyReq', function(proxyReq) proxyReq.setHeader('cookie', 'sessionid=' + cookieSnippedValue) 

【讨论】:

【参考方案2】:

嗨 @tomswift 你的本地服务器是否运行在 http 协议上,但是从远程服务器接收的会话 cookie 带有 Secure; 像:

'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;Secure;']

如果是这样,在本地服务器响应客户端之前,从原始响应(从远程服务器到本地服务器的响应)标头中提取 set-cookie,删除 Secure; 并将其余部分放入代理响应(从本地服务器到客户端的响应)标头,例如:

'set-cookie':
[ 'JSESSIONID=COOKIEWITHSECURE98123; Path=/;HttpOnly;']

然后客户端将自动获取会话cookie。

希望对你有所帮助。

【讨论】:

感谢您提及此@Halt 删除 secure 标志也解决了我与 JSESSIONID 相关的问题 删除“安全”标志时要小心。这意味着 cookie 将通过不安全的连接发送,并且可能会暴露给数据包嗅探器,从而可能泄露用户的登录凭据或敏感的会话信息!【参考方案3】:

理想情况下,代理的工作只是将请求转发到目的地,并且不应该剥离像 cookie 这样的关键标头,但如果是这样,我认为您应该在 https://github.com/nodejitsu/node-http-proxy/issues 处针对它们提出问题。

你还说请求头从不包含cookie,客户端是否可能从未收到它?

【讨论】:

我已在 Web Inspector 中确认客户端收到了“set-cookie”标头。您可以看到交易here。在这种情况下,请求 cookie 是由 Express 的 cookieParser 生成的,我试图用它来支持会话,但它似乎总是做自己的事情。 在 GitHub 中打开了一个问题,因为我努力尝试从代理服务器的响应中获取 cookie 并手动支持会话:github.com/nodejitsu/node-http-proxy/issues/236【参考方案4】:

我找到了一种通过分叉和修改 node-http-proxy 来实现这一点的方法。它服务于我目前的目的,即开发环境。对于任何形式的严肃考虑,都需要将其充实为更合理的解决方案。

详情可参考我在GitHub提交的issue:https://github.com/nodejitsu/node-http-proxy/issues/236#issuecomment-5334457

我希望对此解决方案有一些意见,尤其是如果我完全走错了方向。

【讨论】:

【参考方案5】:

我有类似的问题,cookie 没有传递给客户端。 解决方案:

    从代理响应中获取 cookie 在代理请求中设置,数值稍作修改
let cookie;
const webpackConfig = 
  proxy: 
    '/api': 
        ...
        onProxyReq: (proxyReq) => 
          if(cookie) 
            proxyReq.setHeader('Cookie', cookie);
          
        ,
        onProxyRes: (proxyRes) => 
          const sc = proxyRes.headers['set-cookie'];

          const raw = sc.filter(s => s.startsWith('JSESSIONID'));

          if(raw.length) 
            cookie = raw[0].split(';')[0];
          
        

    
  

【讨论】:

以上是关于通过 node-http-proxy 持久化基于 cookie 的会话的主要内容,如果未能解决你的问题,请参考以下文章

Node-http-proxy 动态路由表?

使用node-http-proxy POST,PUT请求报‘socket hang up’错误

node-http-proxy修改响应结果

使用 node-http-proxy 从 NodeJS 到 Apache 的反向代理不起作用

node-http-proxy - A full-featured http proxy for node.js

在一个端口上有一个应用程序的节点应用程序使用代理服务器(例如 node-http-proxy)有啥意义?