Как обрабатывать пароли БД в строках подключения R?

Хотя я не знаю, каков будет кворум SO, сам вопрос прост: как вы все обрабатываете пароли в строке подключения к базе данных при подключении к базе данных из R?

В учебниках часто приводится такой пример.

con <- dbConnect(MySQL(), user="root", password="test", 
             dbname="research_db", host="localhost",
             client.flag=CLIENT_MULTI_STATEMENTS)

Если база данных действительно является вашим экспериментальным локальным хостом, это может быть несколько реалистично. Однако, если вы используете его с несколькими пользователями на сервере, вы можете не захотеть раскрывать учетные данные базы данных, подобные этому. В частности, при объединении RStudio Server с базой данных SQL вы можете захотеть сделать что-то зашифрованное. Каков ваш опыт?


person Matt Bannert    schedule 23.10.2012    source источник
comment
У @Duncan есть довольно хороший ответ здесь stackoverflow.com/questions/6101605/   -  person Matthew Plourde    schedule 23.10.2012
comment
Вы можете использовать пакет keyringr для подключения к связке ключей ОС. /Брелок.   -  person Josh Gilfillan    schedule 04.01.2017
comment
@JoshGilfillan спасибо, я проверю это, как только у меня будет время, и дам отзыв. Пакет новый?   -  person Matt Bannert    schedule 11.01.2017
comment
@MattBannert Да, это новый, первый выпуск в октябре 2016 года.   -  person Josh Gilfillan    schedule 11.01.2017


Ответы (4)


Вот пример кода, который использует пакет tcltk для запроса пароля, скрывая фактическое значение:

library(tcltk)
tt <- tktoplevel()
pass <- tclVar()
tkpack(tklabel(tt,text='Password:'))
tkpack(tkentry(tt,textvariable=pass,show='*'))
tkpack(tkbutton(tt,text="Done",command=function()tkdestroy(tt)))
tkwait.window(tt)
tclvalue(pass)

В этом случае он просто выводит нескрытый пароль в конце, но вы можете обернуть его в функцию, чтобы вернуть это значение, а затем использовать его в качестве значения для аргумента пароля. Или вы можете поместить это и вызов соединения (со строкой tclvalue в качестве пароля) внутри вызова local, чтобы переменная, содержащая пароль, исчезла, как только она будет использована.

Изменить

Для RStudio и сервера RStudio есть функция .rs.askForPassword. Используйте это как:

psswd <- .rs.askForPassword("Database Password:")
con <- dbConnect(MySQL(), user="root", password=psswd, 
             dbname="research_db", host="localhost",
             client.flag=CLIENT_MULTI_STATEMENTS)
person Greg Snow    schedule 23.10.2012
comment
прикольная идея, что-то в глубине души сомневается хоть что tcltk работает с RStudio server. Могли бы вы представить себе решение с readline, которое также скрывает pw? - person Matt Bannert; 23.10.2012
comment
К сожалению, я пропустил «серверную» часть вопроса. Это будет работать на локальной машине, но я сомневаюсь в Интернете. Существуют способы получить зашифрованный/скрытый пароль с помощью сценариев .cgi, поэтому, возможно, сервер может отправить .cgi, чтобы открыть окно браузера для получения пароля, но это выходит за рамки моего опыта, чтобы комментировать. Я сомневаюсь, что readline будет работать, потому что он использует интерфейс для получения информации, это нужно программировать на уровне интерфейса, а не на уровне readline. - person Greg Snow; 23.10.2012
comment
В любом случае, это был полезный ответ, +1. Заставлять людей вводить свой пароль — хорошее предложение, независимо от того, как оно реализовано. - person Matt Bannert; 23.10.2012
comment
есть хорошее решение для серверной части, если вы используете сервер rstudio, вы можете использовать .rs.askForPassword. Ввод пароля в интерактивном режиме, безусловно, является хорошим предложением. - person Matt Bannert; 13.11.2014
comment
Пакет tcltk недоступен для загрузки. Как называется библиотека? - person Lazarus Thurston; 14.06.2017
comment
@sanjmeh, пакет tcltk должен был быть установлен вместе с R, его не нужно загружать. - person Greg Snow; 14.06.2017
comment
@MattBannert, у Rstudio есть решение для этого, см. редактирование выше. - person Greg Snow; 14.06.2017

Так что мне нравится решение с использованием файла конфигурации - это отличный ответ. Есть также несколько хороших комментариев к ответу на запрос пароля, которые привели меня к этому решению:

conn <- dbConnect(drv, "jdbc:sqlserver://host:port", 'username', password=.rs.askForPassword("Enter password:"))
person benvolioT    schedule 31.03.2016

У меня есть другое решение той же проблемы, которое не требует от пользователя ввода пароля при каждом подключении. Я использую функциональность файла .my.cnf. В основном у каждого пользователя есть файл .my.cnf в корневом каталоге их домашнего каталога RStudio Server, который содержит их пароли ко всем базам данных MySQL, поэтому в сценарии R я просто обращаюсь к базе данных через функциональность «группы».

R-скрипты:

library("RMySQL")
m <- dbDriver("MySQL")
# connect using .my.cnf
con <- dbConnect(m, group = "theDatabase")

.my.cnf файл:

[client]
user = userName
host = mysql.server.com
password = MyPassword
[theDatabase]
database = hr
[theDatabase2]
user = opto
database = opto
password = pure-light
host = merced
person Zoltan Fedor    schedule 26.02.2013
comment
2017: функция dbDriver устарела. Все еще ищу решение. - person Lazarus Thurston; 14.06.2017

Используя пакет Keyring, вы можете реализовать свою функциональность следующим образом.

require(keyring)
require(RMySQL)
keyring::keyring_create("set_keyring_password_here") #Remember this password
keyring::key_set("dbname", keyring = "Your_set_keyring_password_here") 
keyring::key_set("host", keyring = "Your_set_keyring_password_here")
keyring::key_set("port", keyring = "Your_set_keyring_password_here")
keyring::key_set("user", keyring = "Your_set_keyring_password_here")
keyring::key_set("pass", keyring = "Your_set_keyring_password_here")
keyring::key_set("unix.sock", keyring = "Your_set_keyring_password_here")

m<-MySQL() #set the driver to mysql check your database driver and edit
summary(m)
    con<-dbConnect(m, dbname = keyring::key_get("dbname",
                      keyring = "Your_set_keyring_password_here"),
                   host=keyring::key_get("host",
                      keyring = "Your_set_keyring_password_here"),
                   port=as.numeric(keyring::key_get("port",
                      keyring = "Your_set_keyring_password_here")),
                   user=keyring::key_get("user",
                      keyring = "Your_set_keyring_password_here"),
                   pass=keyring::key_get("pass",
                      keyring = "Your_set_keyring_password_here"),
                   unix.sock=keyring::key_get("unix.sock",
                      keyring = "Your_set_keyring_password_here"),
                     )
keyring::keyring_lock("Your_set_keyring_password_here") #Lock keyring after using it.
person Confusion Matrix    schedule 12.08.2019