CakePHP - loginAction的绝对URL

时间:2013-09-14 19:12:15

标签: cakephp cakephp-2.0

由于我们设置AWS托管的方式,我必须使用CakePHP的loginAction的绝对URL。 目前,我的loginAction看起来像这样(现在不起作用)

'loginAction' => array('controller' => 'users', 'action' => 'login'),

将其与来自HTTP的重定向相结合 - > HTTPS我得到一个重定向循环。我可以通过设置这样的绝对URL来证明这一点(工作正常)

'loginAction' => array('https://foo.com'),

我以为我可以将最终的参数设置为真如此

'loginAction' => array('controller' => 'users', 'action' => 'login', TRUE),

但这也不起作用。

我最后的失败我尝试过这样的设置,

'loginAction' => "https://{$_SERVER['HTTP_HOST']}/users/login",

抛出一个完全不相关的错误 - PHP Parse错误:语法错误,意外'''

所以我的问题是,

  • 我可以在loginAction()
  • 中设置绝对URL
  • 或者,我可以告诉Cake总是在某处使用绝对URL,例如routes.php或bootstrap.php吗?

我见过有人在谈论FULL_BASE_URL和其他常数,似乎没有人帮忙。

1 个答案:

答案 0 :(得分:4)

这是我们最近在设置AWS Elastic Beanstalk时遇到的确切问题。问题在于,当负载均衡器命中您的实例时,它实际上使用PORT 80(http),如果您密切关注流程:

  1. 您的AuthComponent使用$controller->redirect()来执行loginRedirect [AuthComponent::419]
  2. redirect()使用Router::url($loginRedirect, true)获取完整网址。 [Controller::774]
  3. Router::url()使用Router::fullBaseUrl()来解析完整的基本网址[Router::899]
  4. Router::fullBaseUrl()使用Configure::read('App.fullBaseUrl')来阅读已写入的完整基本网址。 [Router::929]
  5. 所以问题是,谁解决了fullBaseUrl

    进一步挖掘它,你会在Cake\bootstrap.php中看到,[罪魁祸首在该档案的第158行

    if (!defined('FULL_BASE_URL')) {
        $s = null;
        if (env('HTTPS')) { <---------------- @@@@ env('HTTPS') is false!!!! @@@@
            $s = 's';
        }
    
        $httpHost = env('HTTP_HOST');
    
        if (isset($httpHost)) {
            define('FULL_BASE_URL', 'http' . $s . '://' . $httpHost);
            Configure::write('App.fullBaseUrl', FULL_BASE_URL);
        }
        unset($httpHost, $s);
    }
    

    知道了吗? AWS负载均衡器在端口80上点击你的实例而不告诉你它是一个https调用(以通常的方式),所以蛋糕被愚弄它的http,因此它导致重定向循环。

    我们的解决方案相当hacky。由于我们使用弹性beanstalk并且我们可以编辑环境变量,因此我们在.config

    中的.ebextensions文件中执行此操作
    option_settings:
      - option_name: HTTPS
        value: 1
    

    当我们根本不想要http时(这总是强制重定向使用https)这很好。但更好的是,也许使用HTTP_X_FORWARDED_*变量来确定环境(如果你仍然需要http):

    如果你debug($_SERVER),你应该可以看到类似的内容:

    ["HTTP_X_FORWARDED_FOR"]=>"xx.xx.xx.xx, xx.xx.xx.xx, ...." //note that the first is IP, the rest are proxies
    ["HTTP_X_FORWARDED_PORT"]=>"443"
    ["HTTP_X_FORWARDED_PROTO"]=>"https"
    

    所以这只留下一个选择:编辑bootstrap.php并在顶部添加以下内容:

    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
    }
    

    一旦尝试解析完整的基本网址,您将获得正确的协议集。

    (或者,你可以define('FULL_BASE_URL'..)如果你愿意,但我不喜欢它:p)

    注意

    当我们第一次进入负载平衡世界时,一切都有所不同。如果代码的任何部分行为不正常,请始终检查$_SERVER数组。例如,您不应再依赖$_SERVER['REMOTE_ADDR']了。您需要从$_SERVER['HTTP_X_FORWARDED_FOR']爆炸并检测此变量。

    修改

    如果担心安全问题,请查看此主题。上面的黑客可能很方便,但不能防弹:https://github.com/cakephp/cakephp/issues/2035




    2013年9月15日基于CakePHP 2.4.1的回答,提交085636ea1bb2a57b084456e776bfada01dee71df