Way to securely give a password to R application f

2019-01-07 13:33发布

问题:

Does R have a function that allows a user to provide a password securely, such as Python's getpass module?

(see http://docs.python.org/library/getpass.html for an example of what I mean)

回答1:

The problem is that R does not have functions to control the terminal it is running in (something like Rncurses); probably this is due to portability issues.
Some time ago I was struggling with the same problem and I ended up with a function using TclTk:

getPass<-function(){  
  require(tcltk);  
  wnd<-tktoplevel();tclVar("")->passVar;  
  #Label  
  tkgrid(tklabel(wnd,text="Enter password:"));  
  #Password box  
  tkgrid(tkentry(wnd,textvariable=passVar,show="*")->passBox);  
  #Hitting return will also submit password  
  tkbind(passBox,"<Return>",function() tkdestroy(wnd));  
  #OK button  
  tkgrid(tkbutton(wnd,text="OK",command=function() tkdestroy(wnd)));  
  #Wait for user to click OK  
  tkwait.window(wnd);  
  password<-tclvalue(passVar);  
  return(password);  
}  

Of course it won't work in non-GUI environments.



回答2:

Very simple linux concept for terminal secure password question:

   password <- function(prompt = "Password:"){
      cat(prompt)
      pass <- system('stty -echo && read ff && stty echo && echo $ff && ff=""',
                        intern=TRUE)
      cat('\n')
      invisible(pass)
   }        


回答3:

My package keyringr solves this problem by retrieving passwords from the underlying operating system keyring (DPAPI on Windows, Keychain on OSX and the Gnome Keyring on Linux).

The vignette gives a detailed explanation on how to use the package, but if you were using OSX and have the password saved in Keychain, you could use the following command to return the password to R (where mydb_myuser is the Keychain item name):

install.packages("keyringr")
library("keyringr")
mypwd <- decrypt_kc_pw("mydb_myuser")
print(mypwd)


回答4:

Per m-dz in the comments above, there is a now a package for doing this called getPass, which has a single function, getPass(). This is a replacement for base::readline().



回答5:

Here is a login pop-up, based on ?modalDialog.

library("shiny")

shinyApp(
  ui <- basicPage(
    actionButton("login", "Login"),
    verbatimTextOutput("secrets")
  ),

  server <- function(input, output, session) {
    vals <- reactiveValues(authenticated=FALSE)

    passwordModal <- function(message=NULL) {
      modalDialog(
        textInput("username", "Username", input$username),
        passwordInput("password", "Password", input$password),

        if (!is.null(message)) div(tags$b(message, style="color: red;")),

        footer = tagList(
          modalButton("Cancel"),
          actionButton("authenticate", "OK")
        )
      )
    }

    observeEvent(input$login, {
      showModal(passwordModal())
    })

    observeEvent(input$authenticate, {
      vals$authenticated <- FALSE
      if (!is.null(input$username) && nzchar(input$username) &&
          !is.null(input$password) && nzchar(input$password)) {
        removeModal()

        if (input$password == "letmein") {
          vals$authenticated <- TRUE
        } else {
          showModal(passwordModal(message="Incorrect password!"))
        }

      } else {
        showModal(passwordModal(message="Please fill in your username and password"))
      }
    })

    output$secrets <- renderText({
      if (vals$authenticated) {
        paste("Don't tell anyone, ", input$username, ", but...", sep="")
      } else {
        "I can't tell you that!"
      }
    })
  }
)