ThinkPHP5 PC微信浏览器下突然无法访问

最近接到反馈,说网站无法在电脑微信上打开,提示 页面错误!请稍后再试~,开启调试模式后发现报 Undefined offset: 1 in Lang.php line 204

问题定位

经过排查,应该是微信浏览器近期进行了更新,给服务器传递了 Accept-Language: *。 然后框架的多语言自动侦测逻辑不严谨,导致了此次错误。

出错文件:library/think/Lang.php 出错代码:

代码语言:javascript
复制
        if (isset($_GET[self::$langDetectVar])) {
            // url 中设置了语言变量
            $langSet = strtolower($_GET[self::$langDetectVar]);
        } elseif (isset($_COOKIE[self::$langCookieVar])) {
            // Cookie 中设置了语言变量
            $langSet = strtolower($_COOKIE[self::$langCookieVar]);
        } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            // 自动侦测浏览器语言
            preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
            $langSet     = strtolower($matches[1]);
            $acceptLangs = Config::get('header_accept_lang');
        if (isset($acceptLangs[$langSet])) {
            $langSet = $acceptLangs[$langSet];
        } elseif (isset(self::$acceptLanguage[$langSet])) {
            $langSet = self::$acceptLanguage[$langSet];
        }
    }</code></pre></div></div><p>关键定位:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">// 自动侦测浏览器语言

preg_match('/^([a-z\d-]+)/i', _SERVER[&#39;HTTP_ACCEPT_LANGUAGE&#39;], matches);
// 这里没有判断 preg_match 是否匹配到内容,直接就使用 $matches[1] ,然后就报错了
langSet = strtolower(matches[1]);

解决办法

解决办法很简单,先判断 preg_match,再执行后续代码。

调整后代码:

代码语言:javascript
复制
        if (isset(_GET[self::langDetectVar])) {
// url 中设置了语言变量
langSet = strtolower(_GET[self::$langDetectVar]);
} elseif (isset(_COOKIE[self::langCookieVar])) {
// Cookie 中设置了语言变量
langSet = strtolower(_COOKIE[self::$langCookieVar]);
} elseif (isset(_SERVER[&#39;HTTP_ACCEPT_LANGUAGE&#39;]) &amp;&amp; preg_match(&#39;/^([a-z\d\-]+)/i&#39;, _SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) {
// 自动侦测浏览器语言
langSet = strtolower(matches[1]);
$acceptLangs = Config::get('header_accept_lang');

        if (isset($acceptLangs[$langSet])) {
            $langSet = $acceptLangs[$langSet];
        } elseif (isset(self::$acceptLanguage[$langSet])) {
            $langSet = self::$acceptLanguage[$langSet];
        }
    }</code></pre></div></div><h4 id="5a9pv" name="%E5%BD%B1%E5%93%8D%E7%89%88%E6%9C%AC">影响版本</h4><p>目前主要发现影响 ThinkPHP 5.0 和 5.1 版本,已向官方提交修复,但这两个版本已停止更新,不确定是否会合并。</p><ul class="ul-level-0"><li>ThinkPHP 5.1 PR</li><li>ThinkPHP 5.0 PR</li></ul>