2016-12-15 4 views
2

Я разрабатываю приложение R Shiny и хочу добавить имя пользователя и логины. Я проверил демонстрацию RStudio, но это только использование ShinyServer Pro, и я использую пакет mongolite для резервного копирования formData на Mongodb. Есть ли способ сделать так, чтобы пользовательские логины были вынуждены до создания пользовательского интерфейса приложения?R Shiny: User Authentication for Single app.R

ответ

2

Ну, вы можете сделать это через код с помощью renderUI и сменить пользовательский интерфейс на лету. Вот пример того, как сделать это:

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) 

Урожайность

это при входе в систему:

enter image description here

И это, как только вы вошли в жёстко пароль «пройти».

enter image description here

Из курса программирования этот путь немного неудобно, но вы можете использовать вкладки и скрыть их, возможно, используя подобную логику.

Или, если вы используете shinyServer, вы, вероятно, можете поставить фильтр перед сайтом. Но именно так я подойду к ней в Блестящем.

3

Вы можете добавить проверяющий прокси перед вашим блестящим приложением, как это: https://www.datascienceriot.com/add-authentication-to-shiny-server-with-nginx/kris/

Это скелет конфигурация Nginx, который перенаправляет из HTTPS-порта 443 на вашу Блестящую сервер, работающий на порт 8000.

server { 
    listen  443; 
    server_name shinyservername; 

    ssl     on; 
    ssl_certificate  ... 
    ssl_certificate_key ... 
    ssl_dhparam ... 

    location/{ 
     proxy_pass http://yourdestinationIP:8000; 
     proxy_set_header  X-Forwarded-Proto $scheme; 
     add_header    Front-End-Https on; 
     proxy_set_header  Accept-Encoding ""; 
     proxy_set_header  Host   $host; 
     proxy_set_header  X-Real-IP  $remote_addr; 
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for; 
    auth_basic "Restricted"; 
    auth_basic_user_file /etc/nginx/htpasswd; 
    } 
} 

Установите брандмауэр вашего хоста, чтобы открыть порт 443, и разрешить только LOCALHOST подключения к серверу Shiny на порт 8000:

iptables -A INPUT -p tcp --dport 443 -j ACCEPT 
iptables -A INPUT -p tcp -s localhost --dport 8000 -j ACCEPT 
iptables -A INPUT -p tcp --dport 8000 -j DROP 

Добавить статические учетные данные для одного или нескольких пользователей в /etc/nginx/htpasswd:

htpasswd –c /etc/nginx/htpasswd myshinyuser 

Один недостатка (из многих), что это будет проверять подлинность & Авторизируйтесь, но она не будет проходить проверку подлинности пользователя информации в приложение. Для этого вам понадобится интеграция аутентификации Shiny Server Pro, которая передаст вам пользователя в сеансе.

+0

Связанные решения обескуражены, потому что они могут ломаться так легко и так часто. Это был бы лучший ответ, если бы вы могли добавить некоторую информацию там, чтобы каким-то образом сделать это. Может быть, набросайте, как это работает, или лучший небольшой рабочий пример. –

+0

Спасибо, Майк. Я обновляю через день или два с большей информацией, встроенной в ответ. –

1

Я использую shinyAppLogin вместо shinApp:

# R code 
shinyAppLogin <- function(ui, server, title="Restricted Area", accounts = list(admin="admin"), ...) { 
    ui_with_login <- bootstrapPage(theme = "login_style.css", 
     div(class="login-page", 
      div(class="form", 
       h1(title), br(), 
       tags$form(class="login-form", 
        textInput(inputId = "user", label = NULL, placeholder="Username"), 
        passwordInput(inputId = "pass", label = "", placeholder = "Password"), 
        actionButton(inputId = "login", label = "Login") 
      )))) 

    server_with_login <- function(input, output, session) { 

     observeEvent(input$login, ignoreNULL = T, { 

     if (input$user %in% names(accounts) && input$pass == accounts[[input$user]]) { 

      removeUI(selector = "body", multiple = T, immediate = T, session = session) 
      insertUI(selector = "html", where = "beforeEnd", ui = ui, immediate = T, session = session) 
      server(session$input, session$output, session = session) 
     } 
    }) } 

    shinyApp(ui = ui_with_login, server = server_with_login, ...) 
} 

тогда мой код становится: shinyAppLogin (my_ui, my_server)

Login screen when styles

тогда я использовал CSS от enter link description here просто сохранить CSS в www/login_style.css

2

Вот пример того, как t o использовать файлы cookie для аутентификации. Более подробную информацию можно найти в моем блоге here.

сначала загрузить печенье JS к WWW/папке:

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

download.file(
    url = 'https://raw.githubusercontent.com/js-cookie/js-cookie/master/src/js.cookie.js', 
    destfile = 'www/js.cookies.js' 
) 

Установите необходимые пакеты:

install.packages(c('shiny', 'shinyjs', 'bcrypt')) 

Сохранить следующий код в app.R и нажмите на кнопку "Run App":

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) 
+1

Основываясь на том, что домен вашей ссылки совпадает с вашим именем пользователя, вы, похоже, связаны с вашим собственным сайтом. Если вы это сделаете, вы должны сообщить, что это ваш сайт *. Если вы не раскрываете, что это ваш собственный сайт, он часто считается спамом. См.: [** Что означает «Хорошее» самореклама? **] (// meta.stackexchange.com/q/182212) и [Как не быть спамером] (// stackoverflow.com/help/promotion). – Makyen

+1

Помимо того, что вы, по-видимому, не осознаете, что вам нужно явно раскрывать свою принадлежность, это выглядит как отличный ответ и * далеко * выше того, что большинство людей ставит при связывании своего собственного сайта. Отличная работа. Благодарим за вклад. Но, пожалуйста, сделайте [изменить], чтобы изменить свое второе предложение на что-то вроде «Более подробную информацию можно найти [в моем блоге]». – Makyen

1

ShinyProxy, с открытым исходным кодом Docker- и Spring Java на основе Блестящая сервер был разработан для объявления одевай эту проблему. Он позволяет жестко программировать пользователей в файле конфигурации приложения, подключаться к LDAP-серверу, использовать SSO/Keycloak или социальную сеть.