Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумНастройка и подключение

Спецсимволы в пароле ломают строку подключения

Артур Вагнер
Артур Вагнер
Знаток
сообщений 1290
с мая
8 июня, 11:17первое сообщение

Сгенерировал себе новый пароль, в нём собака, двоеточие и решётка. После этого строка подключения разваливается: библиотека откусывает кусок пароля и считает его именем хоста.

Пароль условно такой: Xk7@ru:si#9. Собираю строку в лоб:

http://login:Xk7@ru:si#9@193.0.2.44:8000

Питон ругается на нечисловой порт, curl молчит и уходит стучаться на ru. Менять пароль на буквенный не хочу, он выдан вместе с пакетом. Как его скормить правильно?

конфиг без комментария это загадка
nastroyka_pro
nastroyka_pro
Ветеран
сообщений 2110
с мар
15 ноября, 14:34#2

Тут нечего чинить в библиотеке, строка подключения читается по правилам адреса. Разделители в ней зарезервированы, и пароль обязан быть закодирован процентами.

СимволКак писать в строке
@%40
:%3A
#%23
/%2F
?%3F
пробел%20

Ваш пароль превращается в Xk7%40ru%3Asi%239, а строка целиком:

http://login:Xk7%40ru%3Asi%239@193.0.2.44:8000

Последняя собака остаётся живой, она отделяет пару входа от адреса. Остальные закодированы, и разбор идёт по нужным границам.

Артур Вагнер
Артур Вагнер
Знаток
сообщений 1290
с мая
22 апреля, 17:51#3
nastroyka_pro: последняя собака остаётся живой

Вот этот момент у меня и путался: я кодировал вообще все собаки, включая разделитель, и получал уже другую ошибку. Питон тогда жаловался на пустой хост.

А если пароль лежит в переменной окружения и строку собирает скрипт, руками же каждый раз не покодируешь?

конфиг без комментария это загадка
hexdump
hexdump
Знаток
сообщений 940
с июн
1 сентября, 08:08#4

Руками и не надо. Кодирование делает та же библиотека, которая потом читает адрес.

import os
from urllib.parse import quote

user = os.environ["PROXY_USER"] pwd = os.environ["PROXY_PASS"] host = "193.0.2.44:8000"

proxy = f"http://{quote(user, safe='')}:{quote(pwd, safe='')}@{host}" proxies = {"http": proxy, "https": proxy} ```

safe='' тут обязательно. Без него quote оставит слеш и двоеточие как есть, и вы вернётесь к тому же месту.

Света Панина
Света Панина
Новичок
сообщений 160
с мар, второй сезон
8 февраля, 11:25#5

а в curl тоже надо кодировать? у меня там пароль с решёткой

hexdump
hexdump
Знаток
сообщений 940
с июн
15 июля, 14:42#6

В curl удобнее вообще не лепить пару в адрес. Есть отдельный флаг, и он берёт значение как есть.

curl -x http://193.0.2.44:8000 -U 'login:Xk7@ru:si#9' -s https://example.org/ip

Кавычки одинарные, иначе решётку съест оболочка. Двоеточий внутри пароля можно не бояться: curl режет по первому, остальное уходит в пароль целиком.

пароль с решёткой без кодирования
пароль с решёткой без кодирования
dev_null_ru
dev_null_ru
Ветеран
сообщений 2560
с фев
22 декабря, 17:59#7

Добавлю сбоку, потому что грабли тут ходят парой и вторую половину обычно не видят.

Список у меня выгружается в формате IP:PORT:LOGIN:PASS, обновляется в реальном времени, и я его читаю скриптом построчно. Пока пароли буквенные, разбор по двоеточию работает. Как только в пароле появляется своё двоеточие, наивный split(":") рассыпается: строка режется на пять частей вместо четырёх, и последний кусок теряется. Лечится ограничением числа разрезов, в питоне это split(":", 3), и тогда всё, что после третьего двоеточия, остаётся паролем целиком.

Второе место, где это вылезает, файлы окружения. Оболочка читает решётку как начало примечания, и половина пароля пропадает ещё до старта программы. Значение в таком файле надо брать в одинарные кавычки.

Я под прогоны беру приватные серверные адреса под парсинг и пароль из кабинета кладу сразу в переменную окружения, чтобы он вообще нигде не встречался в открытом виде в командах.

nastroyka_pro
nastroyka_pro
Ветеран
сообщений 2110
с мар
1 мая, 08:16#8

Ещё проверка на месте: если сомневаетесь, что строка разобралась как задумано, разберите её той же библиотекой и посмотрите поля.

from urllib.parse import urlsplit, unquote
u = urlsplit(proxy)
print(u.hostname, u.port, u.username, unquote(u.password))

Хост и порт должны совпасть с тем, что вы вписывали. Если в хосте оказался обрывок пароля, дальше можно не гадать.

Артур Вагнер
Артур Вагнер
Знаток
сообщений 1290
с мая
8 октября, 11:33#9

Собрал через quote с пустым safe, разобрал обратно через urlsplit, поля сошлись. Прогон пошёл, ошибок входа ноль.

Отдельное спасибо за split(":", 3), у меня ровно там и терялась последняя часть строки, я думал на выгрузку. Тема закрыта.

конфиг без комментария это загадка