Azure 应用服务上的 R Shiny 应用与 Active Directory 集成

Posted

技术标签:

【中文标题】Azure 应用服务上的 R Shiny 应用与 Active Directory 集成【英文标题】:R Shiny app on Azure App Services with Active Directory Integration 【发布时间】:2021-03-16 15:58:39 【问题描述】:

我目前正在将 R Shiny 应用程序部署到 Azure 应用程序服务,并通过 Active Directory 集成限制访问(这似乎在后台使用了 Azure easyauth 代理)。

当我部署 rocker/shiny:3.6.0rocker/shiny:4.0.0 容器以简单地看到“hello world”页面时,部署成功。

当我打开 Active Directory 身份验证时,网站挂起,然后返回 500

我已在此消息的底部附上了错误日志,但我认为它没有任何关于我可以控制的事情的有用信息。

进一步调查表明,如果我部署 rocker:shiny:3.5.2 或更低版本,一切都会按预期工作。如果我部署rocker/shiny:3.6.0 或更高版本,我会得到一个500 并且网站会挂起。

部署rocker/shiny:3.5.3 会导致这些问题中报告的症状:

How do I get Shiny-server to working with Azure Active Directory How to disable websocket on Shiny?

所以我很确定根本原因是不同的。

对我而言,这表明 rocker/shiny:3.6.0 包及以上的更改正在阻止身份验证工作,但恐怕这是我的调试能力停止的地方!

我的问题是 - 我真的只是做错了什么吗?这是一个已知问题吗?我该如何报告(以及向谁报告?!)。

感谢您的帮助,

阿基尔

应用服务错误信息

fail: Middleware[0]
      Unhandled exception in request pipeline: System.Net.Http.HttpRequestException: An error occurred while sending the request.
       ---> System.IO.IOException: The response ended prematurely.
         at System.Net.Http.HttpConnection.FillAsync()
         at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
         at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
         --- End of inner exception stack trace ---
         at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
         at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
         at Microsoft.Azure.AppService.MiddlewareShim.Startup.ForwardRequestAsync(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 197
         at Microsoft.Azure.AppService.MiddlewareShim.Startup.OnRequest(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 151
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "...", Request id "...": An unhandled exception was thrown by the application.
System.Net.Http.HttpRequestException: An error occurred while sending the request.
 ---> System.IO.IOException: The response ended prematurely.
   at System.Net.Http.HttpConnection.FillAsync()
   at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Microsoft.Azure.AppService.MiddlewareShim.Startup.ForwardRequestAsync(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 197
   at Microsoft.Azure.AppService.MiddlewareShim.Startup.OnRequest(HttpContext context) in /EasyAuth/Middleware.Host/Startup.cs:line 151
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application

【问题讨论】:

2 个月后,rocker/shiny-verse:latest 我从不同的途径遇到了同样的问题。使用3.5.2 再次解决了这个问题。 【参考方案1】:

存在一个已知问题,即某些最新版本的节点(或某些其他网络服务器)的标头最大容量为 8KB。

当您启用 EasyAuth 时,它会在请求中添加一些较大的标头。

要克服这个问题,您可以使用以下两种解决方案中的一种:

1.使用WEBSITE_AUTH_DISABLE_IDENTITY_FLOW应用设置

当此变量设置为 true 时,它会禁用分配线程主体标识,这将删除添加到请求 X-MS-CLIENT-PRINCIPAL 的最大标头之一,该标头通常由 .NET Framework 和 Function 应用程序使用。

但是,它包含与 id_token 相同的声明。一个 Base64 编码的 JSON 对象,我们可以对其进行解码以获取信息。如果想直接访问 id_token JWT,可以使用X-MS-TOKEN-AAD-ID-TOKEN header。

参考: https://github.com/cgillum/easyauth/wiki/Advanced-Application-Settings

2。提高标头大小的限制

这可以使用 NODE_OPTIONS 变量来完成,如以下 github 问题 here 中所述。

例如:NODE_OPTIONS=--max-http-header-size=16384

【讨论】:

以上是关于Azure 应用服务上的 R Shiny 应用与 Active Directory 集成的主要内容,如果未能解决你的问题,请参考以下文章

R - Shiny 上的实时图表

R Shiny服务器分段错误

R Shiny selectInput和submitButton并排

带有 if 语句的 ReactiveTimer R-Shiny

如何使用 actionButton 更改 R Shiny 中 selectInput 上的选定值?

如何在Shiny R中丢弃DT :: datatable上的用户编辑