我在Shiny上创建了非常基本和原始的授权。它只检查服务器端的userid-password对,并有条件地显示隐藏的界面。
使用这种原始授权有什么弊端?
library(shiny)
ui <- fluidPage(uiOutput("auth"))
server <- function(input, output) {
output$auth <- renderUI({
tagList(
textInput(inputId = "username",label = "Username"),
passwordInput(inputId = "userpassword",label = "Password"),
actionButton("userlogin", "Login")
)})
observeEvent(input$userlogin, {
if(input$username=="demo" & input$userpassword=="demo") {
output$auth <- renderUI({
tagList(
textInput(inputId = "Secret",label = NULL, placeholder = "Secret Data...")
)})
}
})
}
shinyApp(ui = ui, server = server)
答案 0 :(得分:1)
我不是安全专家,但是潜在的问题让我想到的是隐藏部分的反应性。我相信您需要在大多数反应式的前面加上闪亮的:: validate语句,以防止操纵输入对象触发底层动作。
在这种情况下,假设某些东西取决于该输入的$ Secret输入,他们可以像在其客户端页面上那样创建输入,然后将任何想要的内容提交给您。
现在假设您具有以下部分:
# Insert Secret into database
observeEvent(input$Secret, {
# INSERT RECORD
})
他们可以触发此操作,而无需访问您创建的textInput部分。
一个聪明的演员可以使输入对象成为他们想要的任何对象,因此您需要牢记编写应用程序的每个部分。
这并不是说这是不可能的,但是有很多陷阱,这是一种通过验证来解决上述问题的方法
authorized <- eventReactive(input$submitpass, {
input$username == 'demo' & input$password == 'demo'
})
# Insert Secret into database
observeEvent(input$Secret, {
shiny::validate(need(authorized(), 'You are not authorized'))
# INSERT RECORD
})
编辑:
同样值得注意的是,编写授权很困难,我很想使用现成的东西,而不是尝试自己酿造。尤其是一旦您拥有多个用户并存储/哈希密码后,这就不容易了