【问题标题】:Yii: weird redirect behaviour (https -> http)Yii:奇怪的重定向行为(https -> http)
【发布时间】:2017-02-07 14:07:04
【问题描述】:

我有一个使用 HTTPS 协议运行的整个网站。但是最近我注意到 Yii 的行为很奇怪。当我进行重定向时:

$this->redirect('/article/123456');

它首先执行 302 重定向到页面的 http 版本(我可以通过标题看到):

HTTP://site.xyz/article/123456

X-Powered-By: PHP/5.4.45-0+deb7u2

然后 NGINX 进行 301 重定向到 https 版本:

HTTPS://site.xyz/article/123456

为什么会发生,Yii 是如何构建绝对 URL 的(一直认为它使用相对 URL)?

【问题讨论】:

    标签: php yii


    【解决方案1】:
    /**
         * Redirects the browser to the specified URL.
         * @param string $url URL to be redirected to. Note that when URL is not
         * absolute (not starting with "/") it will be relative to current request URL.
         * @param boolean $terminate whether to terminate the current application
         * @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}
         * for details about HTTP status code.
         */
    public function redirect($url,$terminate=true,$statusCode=302)
        {
            if(strpos($url,'/')===0 && strpos($url,'//')!==0)
                $url=$this->getHostInfo().$url;
            header('Location: '.$url, true, $statusCode);
            if($terminate)
                Yii::app()->end();
        }
    

    Source

    查看有关 URL 参数的注释:

    @param string $url 要重定向到的 URL。 注意,当 URL 不是 * 绝对(不以“/”开头)它将相对于当前请求 URL。

    但是,在您的代码中,URL 以“/”开头,因此根据源代码,接下来会发生的事情是:$url = $this->getHostInfo().$url;

    那么我们来看看getHostInfo函数的来源:

    public function getHostInfo($schema='')
        {
            if($this->_hostInfo===null)
            {
                if($secure=$this->getIsSecureConnection())
                    $http='https';
                else
                    $http='http';
                if(isset($_SERVER['HTTP_HOST']))
                    $this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST'];
                else
                {
                    $this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME'];
                    $port=$secure ? $this->getSecurePort() : $this->getPort();
                    if(($port!==80 && !$secure) || ($port!==443 && $secure))
                        $this->_hostInfo.=':'.$port;
                }
            }
            if($schema!=='')
            {
                $secure=$this->getIsSecureConnection();
                if($secure && $schema==='https' || !$secure && $schema==='http')
                    return $this->_hostInfo;
                $port=$schema==='https' ? $this->getSecurePort() : $this->getPort();
                if($port!==80 && $schema==='http' || $port!==443 && $schema==='https')
                    $port=':'.$port;
                else
                    $port='';
                $pos=strpos($this->_hostInfo,':');
                return $schema.substr($this->_hostInfo,$pos,strcspn($this->_hostInfo,':',$pos+1)+1).$port;
            }
            else
                return $this->_hostInfo;
        }
    

    我建议您检查第一个条件是否返回 true(虽然我认为 _hostInfo 不太可能已定义)并检查 $this->getIsSecureConnection() 函数的结果。

    【讨论】:

    • 谢谢,我找到了问题。服务器未设置 $_SERVER['HTTPS'] (github.com/yiisoft/yii/blob/1.1.17/framework/web/…) 并导致此行为。作为一种解决方法,我在 index.php 中手动设置它并同时寻找更永久的解决方案。
    • 嗯...这种情况比较少见,但如果您按照下一步操作,那就是检查 getIsSecureConnection 函数 (github.com/yiisoft/yii/blob/…) 所以您最终会得出相同的结论.祝你好运。
    猜你喜欢
    • 2010-12-08
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    相关资源
    最近更新 更多