8

我使用 Catalyst 编写了一个 Web 应用程序,它有很多表单并且需要通过 https 运行。没有硬编码的 URL,一切都使用$c->uri_for$c->req->uri. 使用通过 http 运行的开发服务器在开发环境中一切正常。

今天,当我继续部署应用程序时,我发现了一个问题。我们的生产环境当前设置的方式是,客户端浏览器通过 HTTPS 与 F5 负载平衡器通信,而 F5 通过 HTTP 与内部网络上的 Web 服务器通信。

[浏览器]---HTTPS--->[F5]---HTTP--->[Web服务器]

现在,因为 Web 服务器只接收HTTP请求,所以所有的 URI 都是从 HTTP 开始生成的。这表示:

<form action='[% c.uri_for('/secure/form') %]' method='post'>

变成:

<form action='http://websitename.org/secure/form' method='post'>

现在所有浏览器都抱怨您通过不安全的连接提交数据。我需要c.uri_for以 https 开头。

该应用程序今天需要上线,所以我对所有表单操作进行了大规模搜索/替换:

<form action='[% c.uri_for('/secure/form') | replace('http:', 'https:'%]' method='post'>

好吧,现在这破坏了开发,所以我根据配置键对表单操作进行了条件化:

[% IF c.config.production %]
  <form action='[% c.uri_for('/secure/form') | replace ('http:', 'https:') %]' method='post'>
[% ELSE %]
  <form action='[% c.uri_for('/secure/form') %]' method='post'>
[% END %]

不用说,这一切似乎在多个层面上都是错误的。有人有更好的主意吗?有没有办法强制$c->uri_for生成以 https 开头的 URI?

解决方案

如果您使用的是 Catalyst 5.80008 或更高版本,请设置MyApp->config(using_frontend_proxy => 1);并让您的代理设置X-Forwarded-Port标头。对于 5.80008 之前的 Catalyst 版本,仍然进行设置using_frontend_proxy,以便您获得实际的 client_ip,但要生成正确的 URI,请让您的 Web 服务器将环境变量设置HTTPSON

4

3 回答 3

12

你可以试试这个配置选项:

MyApp->config(using_frontend_proxy => 1);

它在Catalyst 的文档中有所描述

于 2009-11-03T04:07:03.993 回答
6

以下作品(已测试):

在 MyApp.pm 中,添加以下子项:

sub secure_uri_for {
    my ($self, @args) = @_;
    my $u = $self->uri_for(@args);
    $u->scheme('https');
    return $u;
}

现在任何时候你想要一个有保证的 https,你都可以打电话$c->secure_uri_for('whatever')

于 2009-11-03T03:50:37.100 回答
1

我不使用 Catalyst,但 docs foruri_for指向请求对象的base方法

我阅读了源代码,发现这base是一种读/写方法。因此,您应该能够在$req->base('https://foo.bar.com/')某处挤入您的代码以获取您的 https uris。

更新:

唱歌鱼说上面的建议是不正确的——这根本不会让我感到惊讶,它是基于对 TFM 的快速浏览。S/He 还说scheme应该设置方法。我假设他/她指的是uri对象的scheme方法。

进一步搜索在 Catalyst Wiki 上出现了 HTTPS Tricks它显示了在方法返回的uri对象上设置方案的示例uri_for_action。看起来您需要在整个代码中为您请求的每个 uri 设置方案。所以,我不禁觉得scheme方法可能不是最好的选择。

我还在邮件列表中找到了这个线程。设置base或设置环境变量都是推荐的方法。

这为您提供了多种调查途径。祝你好运。

于 2009-11-03T02:57:49.373 回答