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, и это самый простой способ, с помощью которого я могу найти приложение, считающее входящее соединение безопасным (не уверенным в других прокси).
-
Создайте самозаверяющий сертификат (см. Https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs или http://www.selfsignedcertificate.com/)
-
На панели Forge вставьте свой закрытый ключ и сертификат через Sites > your-site > SSL Certificates > Install Existing Certificate
.
-
активировать
-
На панели CloudFlare Crypto > SSL
выберите "Полный" (не строго)
- Готово (для распространения изменений потребуется несколько минут)
Короче говоря, соединение между клиентом и Cloudflare защищено собственным SSL Cloudflare. Соединение между сервером приложения и Cloudflare защищено с помощью созданного вами сертификата (таким образом, приложение считает "соединение" безопасным.
Вы можете применить тот же принцип с другими стеками.
Ответ 5
Как я уже упоминал в соответствующем вопросе, я нашел 5 способов создания безопасных URL.
-
Настройте свой веб-сервер для перенаправления всех незащищенных запросов на 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;
}
-
Установите переменную окружения APP_URL
используя https:
APP_URL=https://example.com
-
Используйте помощник secure_url() (Laravel5.6)
-
Добавьте следующую строку в метод AppServiceProvider :: boot() (для версии 5. 4+):
\Illuminate\Support\Facades\URL::forceScheme('https');
-
Неявно задайте схему для группы маршрутов (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'