аватар question@mail.ru · 01.01.1970 03:00

Скрытие логина и пароля в коде Python

Каким образом можно зашифровать логин с паролем в самом коде? Ну или каким-либо другим способом сделать так, чтобы нельзя было бы их получить другим людям, так как сам код должен быть открытым и доступным для просмотра другими людьми.

conn = pymysql.connect(    host=""xxc.ru"",    port=3306,    user=""user"",    password=""password"",    db=""test"",    charset='utf8')

Есть ли смысл использования в данном случае , как в вопросе?

аватар answer@mail.ru · 01.01.1970 03:00

Шифр Цезаря быстренько вскроет любой сообразительный студент вроде меня.

Мухи отдельно, котлеты отдельно: просто не пишите пароль внутри кода, и проблема будет решена сама собой. Кроме того, для подключения к какой-нибудь другой базе данных не нужно будет редактировать код, что повышает удобство. А вот где тогда писать пароль — тут уже много вариантов.

Переменная окружения

В любой «взрослой» ОС есть некие глобальные переменные, именуемые переменными окружения (переменные среды, environment variables). Можно положить пароль туда, а в питоне читать эти переменные. Как менять переменные окружения, зависит от конкретной ОС (можно детали ), а в коде Python их чтение может выглядеть как-нибудь так:

import os, pymysqlconn = pymysql.connect(    host=""xxc.ru"",    user=os.getenv('MYSQL_USER'),    password=os.getenv('MYSQL_PASSWORD'),    # ...)

В данном примере логин читается из переменной окружения MYSQL_USER, а пароль из MYSQL_PASSWORD.

Простой текстовый файл

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

with open('mysql_user.txt', 'r', encoding='utf-8-sig') as fp:    mysql_user = fp.read().rstrip()with open('mysql_password.txt', 'r', encoding='utf-8-sig') as fp:    mysql_password = fp.read().rstrip()conn = pymysql.connect(    host=""xxc.ru"",    user=mysql_user,    password=mysql_password,    # ...)

В данном примере логин и пароль читаются из файлов mysql_user.txt и mysql_password.txt, находящихся в текущем каталоге.

Немного пояснений, почему я читаю файлы именно так:

  • правила хорошего тона предписывают явно закрывать открытые файлы после их использования. Это очень удобно делать с помощью конструкции with;

  • UTF-8 — самая лучшая кодировка на свете, поэтому я прописал её и советую её использовать везде и всегда. Но есть нюанс: виндовый Блокнот добавляет в начале текстового файла, и для его корректной обработки питоном я прописал кодировку utf-8-sig, а не просто utf-8;

  • некоторые текстовые редакторы добавляют перенос строки в конце файла, поэтому я его удаляю с помощью rstrip(), чтоб не мешался.

Полноценный файл конфигурации

Высока вероятность, что вы захотите хранить отдельно от кода не только логин и пароль, так почему бы не завести полноценный конфиг? Можно создать, к примеру, такой файл config.ini:

[mysql]user = логинpassword = пароль

А потом распарсить его в питоне:

import configparser, pymysqlconfig = configparser.ConfigParser()config.read('config.ini', encoding='utf-8-sig')conn = pymysql.connect(    host=""xxc.ru"",    user=config.get('mysql', 'user'),    password=config.get('mysql', 'password'),    # ...)

ConfigParser — очень мощная и универсальная штука; рекомендую почитать хотя бы для общего развития.

Если вы захотите выложить свой код публично на какой-нибудь GitHub, не забудьте добавить свои файлы со всеми паролями в .gitignore, чтобы случайно не опубликовать и их тоже.

Python-модуль с переменными

Можно создать Python-файл, например, local_settings.py, прописать в нём переменные с логином и паролем:

MYSQL_USER = 'Вася'MYSQL_PASSWORD = '123456'

И потом обращаться к ним после импорта:

import local_settings as settingsconn = pymysql.connect(    host=""xxc.ru"",    user=settings.MYSQL_USER,    password=settings.MYSQL_PASSWORD,    # ...)

Так как local_settings.py является полноценным Python-файлом, там можно выполнять какой-нибудь произвольный код, что увеличивает гибкость в сравнении с текстовыми файлами, но в то же время открывает новые способы для выстрела в ногу, так что аккуратно.

Файл должен быть расположен так, чтобы Python его смог найти и импортировать. Он не во всех окружениях может импортировать файлы из текущего каталога, и, если простой импорт как в примере выше у вас не сработает, возможно понадобится прописать переменную окружения PYTHONPATH=. или добавить текущий каталог в список sys.path.

Кстати, все связанные с файлами способы можно комбинировать с переменными окружения. Суть такова: в переменной окружения прописываем, что читать, а Python-код потом читает указанный там файл (или импортирует указанный модуль):

SETTINGS_MODULE=my_mysql_settings

import os, importlib# Это значение по умолчанию на случай, если переменной окружения не будетos.environ.setdefault('SETTINGS_MODULE', 'local_settings')# Импортируем модуль, указанный в переменной окруженияsettings = importlib.import_module(os.getenv('SETTINGS_MODULE'))# Остальное как обычноconn = pymysql.connect(    host=""xxc.ru"",    user=settings.MYSQL_USER,    password=settings.MYSQL_PASSWORD,    # ...)

Таким образом можно завести несколько файлов конфигурации и переключаться между ними с помощью переменной окружения. Подобный подход (в виде более сложном, чем я показал, но похоже) применяется, например, в популярном веб-фреймворке Django; там такая переменная окружения называется DJANGO_SETTINGS_MODULE.

Вообще не хранить ничего и запрашивать в консоли каждый раз

Вбивать пароль от базы данных каждый раз не очень удобно, но всё же тоже вариант. При этом с использованием getpass вводимый текст в консоли не отображается (даже звёздочек нету), так что никто не узнает, какой пароль вы там вводите.

import getpass, pymysqlmysql_user = getpass.getpass('MySQL user> ')mysql_password = getpass.getpass('MySQL password> ')conn = pymysql.connect(    host=""xxc.ru"",    user=mysql_user,    password=mysql_password,    # ...)

Последние

Похожие