Laravel создает безопасный URL-адрес https с маршрута

редактировать

Я не могу найти способ сгенерировать безопасный URL из имени маршрута.

Чтобы получить полный URL, я использую

echo route('my_route_name');

Но что делать, если я хочу URL с https?

Ответы

Ответ 1

На самом деле получается, что laravel не заботится о том, безопасен ли URL-адрес или нет, потому что он генерируется на основе текущего URL-адреса. Если вы находитесь на странице https, route() вернет защищенный URL. Если на http, то http:// url

Проблема заключалась в том, что Laravel не обнаружил, что https включен, что было вызвано неправильной конфигурацией сервера.

Вы можете проверить, видит ли Laravel текущее соединение как https, вызывая Request::isSecure();

Ответ 2

ОБНОВЛЕНИЕ: Как указано в комментариях, более простой способ сделать это - добавить URL::forceSchema('https'); для версии Laravel между 4.2-5.3 или URL::forceScheme('https'); для версии 5.4+ в boot вашего файла AppServiceProvider.

Старый ответ:

Это действительно возможно, и для выполнения этого требуется только одна строка кода.

Laravel не проверяет наличие SSL самостоятельно, это зависит от Symfony. И есть наш ключ к тому, чтобы он считал, что текущий запрос является безопасным.

Дело в том, что мы должны установить значение HTTPS server param в true, а самый простой способ - вставить следующий код в метод boot вашего AppServiceProvider:

$this->app['request']->server->set('HTTPS', true);

В моем случае, мне нужно только принудительно использовать SSL в процессе производства, локальный env должен по-прежнему работать на http. Вот как я принудительно применяю SSL только к производству:

$this->app['request']->server->set('HTTPS', $this->app->environment() != 'local');
Кстати, помните эти термины, они могут понадобиться им в будущем.

Ответ 3

Я думаю, что есть только один способ сделать это.

Чтобы создать безопасный URL-адрес для ваших именованных маршрутов, вы можете передать свой маршрут в вспомогательную функцию secure_url.

secure_url(URL::route('your_route_name', [], false));

Вы не можете использовать вспомогательную функцию route, потому что она генерирует абсолютный URL (с http://) по умолчанию, а http не версия https, которую вы хотели

Ответ 4

Laravel 5.x сгенерирует безопасный URL с помощью помощника route(), если обнаружит, что входящее соединение защищено. Проблема обычно возникает, если приложение скрыто за балансировщиком нагрузки или прокси-сервером (например, Cloudflare), поскольку соединение между сервером приложения и балансировщиком нагрузки/прокси-сервером может быть небезопасным.

Сейчас я использую Laravel Forge + Cloudflare, и это самый простой способ, с помощью которого я могу найти приложение, считающее входящее соединение безопасным (не уверенным в других прокси).

  1. Создайте самозаверяющий сертификат (см. Https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs или http://www.selfsignedcertificate.com/)

  2. На панели Forge вставьте свой закрытый ключ и сертификат через Sites > your-site > SSL Certificates > Install Existing Certificate.

  3. активировать

  4. На панели CloudFlare Crypto > SSL выберите "Полный" (не строго)

  5. Готово (для распространения изменений потребуется несколько минут)

Короче говоря, соединение между клиентом и Cloudflare защищено собственным SSL Cloudflare. Соединение между сервером приложения и Cloudflare защищено с помощью созданного вами сертификата (таким образом, приложение считает "соединение" безопасным.

Вы можете применить тот же принцип с другими стеками.

Ответ 5

Как я уже упоминал в соответствующем вопросе, я нашел 5 способов создания безопасных URL.

  1. Настройте свой веб-сервер для перенаправления всех незащищенных запросов на https. Пример конфигурации nginx:

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name example.com www.example.com;
        return 301 https://example.com$request_uri;
    }
    
  2. Установите переменную окружения APP_URL используя https:

    APP_URL=https://example.com
    
  3. Используйте помощник secure_url() (Laravel5.6)

  4. Добавьте следующую строку в метод AppServiceProvider :: boot() (для версии 5. 4+):

    \Illuminate\Support\Facades\URL::forceScheme('https');
    
  5. Неявно задайте схему для группы маршрутов (Laravel5.6):

    Route::group(['scheme' => 'https'], function () {
        // Route::get(...)->name(...);
    });
    

    На данный момент этот способ не задокументирован, но работает хорошо.

Ответ 6

Использовать secure_url:

secure_url(URL::route('your_route_name', [], false));

Вам нужно будет установить URL:: route в false, чтобы не возвращать полный URL. Затем используйте функцию secure_url, которая генерирует полный URL HTTPS для данного пути.

В интерфейсе UrlGenerator вы можете использовать URL:: route

string route(string $name, mixed $parameters = array(), bool $absolute = true)

Get the URL to a named route.
Parameters
string  $name   
mixed   $parameters     
bool    $absolute   
Return Value
string

https://laravel.com/api/5.4/Illuminate/Contracts/Routing/UrlGenerator.html

Ответ 7

В большинстве случаев маршруты должны генерироваться с той же схемой, на которой был загружен ваш сайт. Laravel автоматически определяет, имеет ли запрос заголовок X-Forwarded-Proto и использует его, чтобы решить, какую схему использовать в сгенерированных URL маршрута. Если ваш сайт находится за обратным прокси-сервером, вы должны добавить обратный прокси-адрес IP-адреса в список доверенных прокси. https://github.com/fideloper/TrustedProxy пакет помогает это сделать. Это включено в Laravel 5.5. Например, мой config/trustedproxy.php выглядит так:

<?php

return [
    'proxies' => '*',

    'headers' => [
    ]
];

Я использую его с обратным прокси-сервером nginx, который имеет следующую конфигурацию:

server {
  listen 80;
  server_name example.com; 
  access_log  /var/log/nginx/example.com_access.log;
  error_log   /var/log/nginx/example.com_error.log;

  client_max_body_size 50m;

  location / {
    proxy_pass              http://localhost:8002;
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
  }

  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;


  if ($scheme != "https") {
    return 301 https://$host$request_uri;
  }
}

Замените example.com на свой домен. Сертификаты SSL были предоставлены Разрешить шифрование с certbot.

Ответ 8

На laravel 5.5. * Вам нужно всего лишь добавить https в ваш файл .env, так как в AppServiceProvider уже есть функция, которая проверяет, имеет ли ваш APP_URL или app.url в вашей конфигурации https.

class AppServiceProvider extends ServiceProvider
{
 public function boot()
 {

    \URL::forceRootUrl(\Config::get('app.url'));    
    if (str_contains(\Config::get('app.url'), 'https://')) {
        \URL::forceScheme('https');
    }
 }

Ответ 9

Для будущих посетителей:

Функция secure_url неправильно обрабатывает параметры GET. Так, например, если вы хотите преобразовать URL-адрес, который пользователь посетил в безопасный URL-адрес, сохраняя при этом поля GET, вы должны использовать это:

secure_url(Request::path()).'?'.http_build_query(Input::all());

В частности обратите внимание на использование path(), а не url() - если вы дадите ему полный URL-адрес, он не заменит http в начале, делая его бесполезным.

Ответ 10

Я столкнулся с этой проблемой, пытаясь создать маршрут как действие формы в Blade, используя Laravel 5.4. Затем я надавил на secure_url(), поэтому я попробовал

{{ secure_url(route('routename', $args)) }} 

Это все еще возвращает небезопасный URL.: - (

После обработки кода и добавления некоторых журналов отладки, я наконец понял, что secure_url не изменяет входящий аргумент url, если он уже является абсолютным URL (включая схему).

К счастью, маршрут имеет абсолютный флаг в качестве третьего аргумента и возвращает относительный URL, если $absolute передается как false.

Предполагая, что /a/ {id}/b - именованный маршрут "a.b"

route('a.b', 1)        : will return http://[domain]/a/1/b 
route('a.b', 1, false) : will return /a/1/b

Присоединение к двум, к которым я пришел:

{{ secure_url(route('routename', $args, false)) }}

Как и ожидалось, он сгенерировал https://[domain]/routeXXX

: -)

Ответ 11

Согласно документации laravel о вспомогательном методе url().

Если путь не указан, возвращается экземпляр Illuminate\Routing\UrlGenerator

Таким образом, вы можете использовать безопасный метод класса UrlGenerator следующим образом:

echo url()->secure('my_route_name');

Ответ 12

Поместите это в файл filters.php и повсюду будет зависеть от https, сохраняя параметры URL:

//force ssl
App::before(function () {
if(!Request::secure() && App::environment() != 'local')
{
    $baseHost = Request::getHttpHost();
    $requestUri = Request::getRequestUri();
    $newLink = 'https://'.$baseHost.$requestUri;

    return Redirect::to($newLink);
}});

Ответ 13

Чтобы создать безопасный маршрут (https), используйте следующий встроенный фильтр "before", называемый "auth":

Например:

Route::get('your-route', ['before' => 'auth', 'uses' => [email protected]']);

Теперь, когда вы выводите свою ссылку, она будет добавлена ​​с помощью 'https'