R Shiny:单个app.R的用户身份验证

Dan*_*ith 13 authentication r shiny

我正在开发一个R Shiny应用程序,并希望添加用户名和登录.我检查了RStudio演示但是只使用了ShinyServer Pro,我使用mongolite软件包将formData备份到Mongodb.

有没有办法在生成应用程序UI之前添加用户登录?

Joh*_*n D 13

ShinyProxy是一个开源的Docker和基于Spring Java的Shiny服务器,旨在解决这个问题.它允许您对应用程序配置文件中的用户进行硬编码,连接到LDAP服务器,使用SSO/Keycloak或社交网络登录.


Cal*_*oss 9

以下是如何使用cookie进行身份验证的示例.更多信息可以在我的博客中找到.

首先将cookie js下载到www /文件夹:

if (!dir.exists('www/')) {
    dir.create('www')
}

download.file(
  url = 'https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js',
  destfile = 'www/js.cookies.js'
)
Run Code Online (Sandbox Code Playgroud)

安装必要的包:

install.packages(c('shiny', 'shinyjs', 'bcrypt'))
Run Code Online (Sandbox Code Playgroud)

将以下代码保存为app.R并单击"运行应用程序"按钮:

library(shiny)
library(shinyjs)
library(bcrypt)


# This would usually come from your user database.

# Never store passwords as clear text
password_hash <- hashpw('secret123') 

# Our not so random sessionid
# sessionid <- paste(
#   collapse = '', 
#   sample(x = c(letters, LETTERS, 0:9), size = 64, replace = TRUE)
# )
sessionid <- "OQGYIrpOvV3KnOpBSPgOhqGxz2dE5A9IpKhP6Dy2kd7xIQhLjwYzskn9mIhRAVHo" 


jsCode <- '
  shinyjs.getcookie = function(params) {
    var cookie = Cookies.get("id");
    if (typeof cookie !== "undefined") {
      Shiny.onInputChange("jscookie", cookie);
    } else {
      var cookie = "";
      Shiny.onInputChange("jscookie", cookie);
    }
  }
  shinyjs.setcookie = function(params) {
    Cookies.set("id", escape(params), { expires: 0.5 });  
    Shiny.onInputChange("jscookie", params);
  }
  shinyjs.rmcookie = function(params) {
    Cookies.remove("id");
    Shiny.onInputChange("jscookie", "");
  }
'

server <- function(input, output) {

  status <- reactiveVal(value = NULL)
  # check if a cookie is present and matching our super random sessionid  
  observe({
    js$getcookie()
    if (!is.null(input$jscookie) && 
        input$jscookie == sessionid) {
          status(paste0('in with sessionid ', input$jscookie))
    }
    else {
      status('out')
    }
  })

  observeEvent(input$login, {
    if (input$username == 'admin' & 
        checkpw(input$password, hash = password_hash)) {
      # generate a sessionid and store it in your database,
      # sessionid <- paste(
      #   collapse = '', 
      #   sample(x = c(letters, LETTERS, 0:9), size = 64, replace = TRUE)
      # )
      # but we keep it simple in this example...
      js$setcookie(sessionid)
    } else {
      status('out, cause you don\'t know the password secret123 for user admin.')
    }
  })

  observeEvent(input$logout, {
    status('out')
    js$rmcookie()
  })

  output$output <- renderText({
    paste0('You are logged ', status())}
  )
}

ui <- fluidPage(
  tags$head(
    tags$script(src = "js.cookies.js")
  ),
  useShinyjs(),
  extendShinyjs(text = jsCode),
  sidebarLayout(
    sidebarPanel(
      textInput('username', 'User', placeholder = 'admin'),
      passwordInput('password', 'Password', placeholder = 'secret123'),
      actionButton('login', 'Login'),
      actionButton('logout', 'Logout')
    ),
    mainPanel(
      verbatimTextOutput('output')
    )
  )
)

shinyApp(ui = ui, server = server)
Run Code Online (Sandbox Code Playgroud)

  • 除了你显然没有意识到你需要明确披露你的联盟,这看起来是一个很好的答案,并且远远高于大多数人在链接他们自己的网站时所提出的.做得好.感谢您的贡献.但是,请[编辑]将您的第二句改为"可以在我的博客上找到更多信息". (3认同)

Mik*_*ise 6

好吧,你可以通过代码使用renderUI和动态更改UI来实现.以下是如何执行此操作的示例:

library(shiny)
library(ggplot2)

u <- shinyUI(fluidPage(
  titlePanel("Shiny Password"),

  sidebarLayout(position = "left",
                sidebarPanel( h3("sidebar panel"),
                              uiOutput("in.pss"),
                              uiOutput("in.clr"),
                              uiOutput("in.titl"),
                              uiOutput("in.cnt"),
                              uiOutput("in.seed")

                ),
                mainPanel(h3("main panel"),
                          textOutput('echo'),
                          plotOutput('stdplot')
                )
  )
))

pok <- F

s <- shinyServer(function(input, output) 
{
  output$in.pss   <- renderUI({ input$pss; if (pok) return(NULL) else return(textInput("pss","Password:","")) })
  output$in.clr   <- renderUI({ input$pss; if (pok) return(selectInput("clr","Color:",c("red","blue"))) else return(NULL) })
  output$in.titl  <- renderUI({ input$pss; if (pok) return(textInput("titl","Title:","Data")) else return(NULL) })
  output$in.cnt   <- renderUI({ input$pss; if (pok) return(sliderInput("cnt","Count:",100,1000,500,5)) else return(NULL) })
  output$in.seed  <- renderUI({ input$pss; if (pok) return(numericInput("seed","Seed:",1234,1,10000,1)) else return(NULL) })
  histdata <- reactive(
    {
      input$pss;
      validate(need(input$cnt,"Need count"),need(input$seed,"Need seed"))
      set.seed(input$seed)
      df <- data.frame(x=rnorm(input$cnt))
    }
  )
  observe({
     if (!pok) {
       password <- input$pss
       if (!is.null(password) && password == "pass") {
         pok <<- TRUE
       }
     }
   }
  )
  output$echo = renderText(
    {
      if (pok) {
        s <- sprintf("the %s is %s and has %d rows and uses the %d seed",
           input$ent,input$clr,nrow(histdata()),input$seed)
      } else {
        s <- ""
      }
      return(s)
    }
  )
  output$stdplot = renderPlot(
    {
      input$pss
      if (pok) {
        return(qplot(data = histdata(),x,fill = I(input$clr),binwidth = 0.2,main=input$titl))
      } else {
        return(NULL)
      }
    }
  )
}
)
shinyApp(ui=u,server=s)
Run Code Online (Sandbox Code Playgroud)

产量

这在登录时:

在此输入图像描述

一旦你输入了硬编码密码"pass".

在此输入图像描述

当然这种编程方式有点尴尬,但您可以使用制表符并使用类似的逻辑隐藏它们.

或者,如果您使用的是shinyServer,则可能会在网站前放置一个过滤器.但这就是我在Shiny中接近它的方式.

  • 感谢您提供此代码示例。我已经将它自定义为使用闪亮的示例应用程序,它只需要闪亮的库:https://gist.github.com/ofhouse/856b17c929f5a30efa0f7d3fc421d5e6 (3认同)

And*_*ino 5

所述polishedř包添加认证和用户管理的任何应用闪亮:https://github.com/Tychobra/polished

这是您使用优美的默认登录页面的屏幕截图: 默认抛光登录页面
您可以在登录和注册页面上使用您自己的品牌轻松替换占位符徽标和颜色。

Polished 还带有一个仪表板来管理您的应用程序的用户:


更多细节:https : //polished.tech/