如何结合shinymanager与session$onSessionEnded()实现浏览器关闭时关闭Shiny应用?
解决shinymanager下session$onSessionEnded()不生效的问题
问题原因
shinymanager的登录流程会先创建一个临时session用于身份验证,登录成功后才会生成用户实际使用的应用session。如果直接在server函数顶层绑定session$onSessionEnded(),这个事件会绑定到临时的登录session上,而非用户操作的真实session,因此浏览器关闭时无法触发预期的应用关闭逻辑。
解决方案
将session$onSessionEnded()绑定到secure_server()的回调函数内部,这个回调会在用户登录成功后执行,其中的session对象就是用户的真实应用session,能正确捕获会话结束事件。
修改后的示例代码
library(shiny) library(shinymanager) # 配置登录凭证 credentials <- data.frame( user = c("admin"), password = c("admin"), stringsAsFactors = FALSE ) # 应用UI ui <- secure_app( fluidPage( h3("登录成功后的应用内容") ) ) # 应用Server server <- function(input, output, session) { res_auth <- secure_server( check_credentials = check_credentials(credentials), # 登录成功后的回调函数,处理真实session function(input, output, session) { # 绑定会话结束事件 session$onSessionEnded(function() { cat("用户会话已结束,关闭应用\n") stopApp() }) # 这里添加你的应用业务逻辑 } ) } shinyApp(ui, server)
进阶:多用户场景下的应用关闭逻辑
如果你的应用支持多用户登录,希望最后一个用户退出时再关闭应用,可以通过全局变量统计活跃会话数:
library(shiny) library(shinymanager) credentials <- data.frame( user = c("admin", "user1"), password = c("admin", "user1"), stringsAsFactors = FALSE ) # 全局变量:记录当前活跃会话数 active_sessions <- 0 ui <- secure_app( fluidPage( h3("多用户测试应用"), verbatimTextOutput("session_count") ) ) server <- function(input, output, session) { res_auth <- secure_server( check_credentials = check_credentials(credentials), function(input, output, session) { # 登录成功,增加活跃会话数 active_sessions <<- active_sessions + 1 # 显示当前活跃会话数 output$session_count <- renderPrint({ paste("当前活跃会话数:", active_sessions) }) session$onSessionEnded(function() { # 会话结束,减少活跃会话数 active_sessions <<- active_sessions - 1 cat("会话结束,当前活跃会话数:", active_sessions, "\n") # 无活跃会话时关闭应用 if (active_sessions == 0) { stopApp() } }) } ) } shinyApp(ui, server)
内容的提问来源于stack exchange,提问作者Santhosh Manikandan
相关产品推荐
相关产品推荐

