You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ShinyProxy集成Keycloak+Nginx+R Shiny登出时出现UT015005错误

问题解决:ShinyProxy登出时UT015005错误

问题背景

环境为集成Keycloak、ShinyProxy与Nginx的R Shiny应用,用户执行登出操作时可正常跳转至登录页,但ShinyProxy日志中出现如下错误:

2025-03-06 12:59:44 2025-03-06T08:59:44.394Z INFO 1 --- [ XNIO-1 task-5] e.o.containerproxy.service.UserService : User logged out [user: testuser] 2025-03-06 12:59:44 2025-03-06T08:59:44.410Z ERROR 1 --- [ XNIO-1 task-5] io.undertow.servlet.request : UT015005: Error invoking method sessionDestroyed on listener class org.springframework.security.web.session.HttpSessionEventPublisher 

临时方案(先停止Shiny应用再登出)因后续要禁用开发者导航栏不可行。

问题原因

该错误源于会话销毁时序冲突:当用户直接登出时,Shiny应用的WebSocket连接仍处于活跃状态,ShinyProxy销毁HttpSession时,Spring Security的HttpSessionEventPublisher监听器尝试处理已被部分释放的会话资源,导致调用失败。

解决方案

1. 配置ShinyProxy会话超时与资源清理

在application.yml中添加会话超时配置,确保会话销毁时资源被正确释放:

proxy:
  # 新增会话超时配置(单位:秒,示例为3600秒即1小时)
  session-timeout: 3600
  # 调整心跳超时为合理值,避免僵尸会话
  heartbeat-timeout: 3600
  # 保留原有配置...

2. 优化自定义登出流程(适配应用内导航栏)

在R Shiny应用的自定义导航栏中,添加JavaScript代码,先关闭Shiny的WebSocket连接,再触发ShinyProxy的登出请求:

library(shiny)

ui <- fluidPage(
  tags$script(HTML('
    function customLogout() {
      // 关闭Shiny的WebSocket连接
      if (window.Shiny && window.Shiny.shinyapp && window.Shiny.shinyapp.connection) {
        window.Shiny.shinyapp.connection.close();
      }
      // 延迟触发登出,确保连接关闭完成
      setTimeout(() => {
        window.location.href = "/logout";
      }, 100);
    }
  ')),
  # 自定义导航栏示例
  navbarPage(
    "自定义导航",
    tabPanel("首页"),
    navbarMenu(
      "账户",
      actionLink("logoutBtn", "登出", onclick = "customLogout()")
    )
  )
)

server <- function(input, output, session) {
  # 服务器逻辑
}

shinyApp(ui, server)

3. 修正OpenID配置的一致性问题

application.yml中auth-url和logout-url需保持内外网地址一致性,内部容器通信使用Docker网络名称keycloak:

proxy:
  openid:
    # 修正auth-url为内部容器地址(外部请求由Nginx转发)
    auth-url: keycloak:8080/auth/realms/shinyrealm/protocol/openid-connect/auth
    # 修正logout-url的内部调用地址
    logout-url: keycloak:8080/auth/realms/shinyrealm/protocol/openid-connect/logout?id_token_hint=#{oidcUser.idToken.tokenValue}&post_logout_redirect_uri=http%3A%2F%2Flocalhost
    # 保留原有配置...

注:Nginx已配置/auth/路径转发,外部用户访问时会自动映射为localhost/auth/。

4. 调整Nginx的WebSocket连接管理

在Nginx的location /块中,添加WebSocket存活检测配置,主动清理失效连接:

location / {
    proxy_pass http://shinyproxy:8080/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Prefix /;
    
    # WebSocket支持增强
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600;
    # 新增:开启WebSocket长连接检测
    proxy_socket_keepalive on;
}

验证方法

  1. 重启所有容器:docker-compose down && docker-compose up -d
  2. 登录应用后直接点击自定义导航栏的登出按钮
  3. 查看ShinyProxy日志,确认UT015005错误不再出现

内容的提问来源于stack exchange,提问作者Reaperz Reaperz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:45:05