zoukankan      html  css  js  c++  java
  • laravel + haproxy + https 后生成分页 url 非 https 解决办法

    更合适的解决办法:在 AppServiceProvider boot 方法中使用 URL::forceScheme('https'); 即可。

    背景

    近日对所有的客户都上线了 https ,本来在 beta 环境中是没有任何问题,都测试通过了,但是在正式上线后,发现后台管理系统中的 laravel 分页生成的 url 是非 https 的,但是其他地方(路由,静态资源)等生成的都是正常的 https 链接,遂找原因解决。

    解决

    laravel 的分页服务 IlluminatePaginationPaginationServiceProvider::class 找到该 ServiceProvider 源码中 register() 中的代码

    Paginator::currentPathResolver(function () {
            return $this->app['request']->url();
    });

    可以看到分页链接生成的时候,是根据当前请求的 url 来设置分页类的 url path.

    接着找到 IlluminateHttpRequest::class 中的 url()

        public function url()
        {
            return rtrim(preg_replace('/?.*/', '', $this->getUri()), '/');
        }

    在这里我们可以发现 laravel 的 Request 类是继承自 Symfony 的 Request,通过不断地位我们可以找到如下代码:

        public function isSecure()
        {
            if ($this->isFromTrustedProxy() && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && $proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO])) {
                return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
            }
    
            $https = $this->server->get('HTTPS');
    
            return !empty($https) && 'off' !== strtolower($https);
        }

    看到这段源码后,我们打印了生产环境中的 phpinfo

    通过源码对比发现,Symfony 中默认读取的是 X_FORWARDED_PROTO and X_FORWARDED_PORT,但是我们 php 环境中是 HTTP_X_FORWARDED_PROTO and HTTP_X_FORWARDED_PORT,我们在源码中发现了如下方法:

        /**
         * Sets the name for trusted headers.
         *
         * The following header keys are supported:
         *
         *  * Request::HEADER_CLIENT_IP:    defaults to X-Forwarded-For   (see getClientIp())
         *  * Request::HEADER_CLIENT_HOST:  defaults to X-Forwarded-Host  (see getHost())
         *  * Request::HEADER_CLIENT_PORT:  defaults to X-Forwarded-Port  (see getPort())
         *  * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure())
         *
         * Setting an empty value allows to disable the trusted header for the given key.
         *
         * @param string $key   The header key
         * @param string $value The header name
         *
         * @throws InvalidArgumentException
         */
        public static function setTrustedHeaderName($key, $value)
        {
            if (!array_key_exists($key, self::$trustedHeaders)) {
                throw new InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key));
            }
    
            self::$trustedHeaders[$key] = $value;
        }

    可以发现这是一个静态方法,因此我们只需要在 AppServiceProvider 中加入如下代码即可

     
    Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT,'HTTP_X_FORWARDED_PORT');
    Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO,'HTTP_X_FORWARDED_PROTO');


    讨论交流

  • 相关阅读:
    Digital Video Stabilization and Rolling Shutter Correction using Gyroscope 论文笔记
    Distortion-Free Wide-Angle Portraits on Camera Phones 论文笔记
    Panorama Stitching on Mobile
    Natural Image Stitching with the Global Similarity Prior 论文笔记 (三)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(二)
    Natural Image Stitching with the Global Similarity Prior 论文笔记(一)
    ADCensus Stereo Matching 笔记
    Efficient Large-Scale Stereo Matching论文解析
    Setting up caffe on Ubuntu
    Kubernetes配置Secret访问Harbor私有镜像仓库
  • 原文地址:https://www.cnblogs.com/iBrand2018/p/8780934.html
Copyright © 2011-2022 走看看