html - 如何在不将应用程序暴露在其他地方的情况下将服务器端 Shiny 应用程序嵌入到 JSP 页面中
问题描述
我有一个 Shiny 应用程序,我想将它嵌入到托管在 Amazon AWS 上的 Java 8 网络服务器的页面中。(注意:我说“嵌入”是因为网络服务器中的大多数页面共享一个公共侧边栏和页脚 - 这会自动应用于大多数视图,因此 .jsp 文件只需为页面的真实内容提供 html)。
Shiny 应用程序在 3305 上侦听,网络服务器在 localhost 上托管到 :8080([server ip]/subject/index.html 可以正常通过其他机器获取网页)。
通过包含 的 shiny.jsp 嵌入 Shiny 应用程序对 localhost 来说效果很好<iframe src="http://localhost:3305">
,但是当从另一台机器查看时,该页面仅在该另一台机器上查找闪亮的服务器,而它应该在主机上查找。去掉“http://”会导致 Shiny 应用程序永远不会收到请求并且页面保持空白,并且将“localhost”与“127.0.0.1”交换会导致没有明显的变化。
该服务器使用 Spring、JSTL 和 Apache Tomcat 7.0。
我不能简单地移植 Shiny 应用程序以使其在服务器外部可见,因为该应用程序显示机密信息。在 .jsp 中,这不是问题,因为 iframe 可以包装在<security:authorize>
标签中(网站首先需要登录才能访问任何页面)。
问题是,将 Shiny 应用程序嵌入到 .jsp 页面中的最简单方法是什么,以使其对用户保持交互但又安全(在没有服务器外部授权的情况下无法直接访问)并且不需要额外的登录?
解决方案
一个 la spring mvc rest service redirect / forward / proxy,一个 Controller 镜像 Shiny 应用,这样我们就保留了访问控制:
import java.net.URI;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
@Controller
public class ShinyController
{
private static final RestTemplate restTemplate = new RestTemplate();
@RequestMapping(path = "/shiny-proxy/**")
public ResponseEntity<String> mirrorRest(@RequestBody(required = false) String body,
HttpMethod method, HttpServletRequest request) throws URISyntaxException {
String path = StringUtils.removeStart(
request.getRequestURI(), "/project/shiny-proxy");
URI uri = new URI(request.getScheme(), null, "localhost", 3305,
path, request.getQueryString(), null);
HttpHeaders headers = new HttpHeaders();
if (path.endsWith(".css.map")) {
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
}
HttpEntity<String> httpEntity = new HttpEntity<>(body, headers);
return restTemplate.exchange(uri, method, httpEntity, String.class);
}
}
这将处理闪亮页面的 HTML 及其所有资源。在 JSP 视图中,
<iframe src="shiny-proxy/">
现在我们只需要处理 ws://[shiny url]/websocket/ 请求。
在 web.xml 中,防止网络服务器通过以下方式处理它:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/project/shiny-proxy/websocket/</url-pattern>
</servlet-mapping>
然后,启用Include conf/extra/httpd-vhosts.conf
,/opt/bitnami/apache2/conf/httpd.conf
并将httpd-vhosts.conf
的内容设置为:
<VirtualHost *:80>
RewriteEngine on
RewriteRule /project/shiny-proxy/websocket/(.*) ws://localhost:3305/websocket/$1 [P,L]
</VirtualHost>
所以...原来很简单。
推荐阅读
- javascript - 如何使用 jQuery 控制分页、选择过滤器和搜索组合的数据流
- python - 映射一个键盘键作为我的鼠标左键单击
- mysql - 创建一个 mysql 表视图,根据其值“合并”表中的两列,并从 DateTime 类型列中选择其最近的日期
- flutter - ParentDataWidget 的使用不正确。颤振应用
- pandas - 将分组刻度添加到条形图
- excel - Office 脚本范围内的最后一行
- vtk - 将大型 3D NumPy 数组加载到 Paraview
- sql-server-2008 - SQL Server Management Studio 中的自定义分隔符不起作用
- javascript - 反应settimeout函数导致页面重复刷新
- python - mysql.connector.errors.ProgrammingError: 1064 (42000