【发布时间】:2021-07-14 15:30:45
【问题描述】:
以下是我们拥有/想要实施的场景:
- 我们在 apache tomcat 上部署了一个基于 java spring 的 Web 应用程序。
- 在我们的 Web 应用程序中,我们将为用户提供一个基于 .net 的第三方 Web 应用程序链接。单击哪个用户将被重定向到 .net 应用程序,但浏览器 url 中显示的域和上下文根将保持与 java 应用程序相同。
- 我们不能要求第 3 方团队更改其应用程序中的任何内容。
- 我们必须更改的内容应该在我们的代码中,而且我们应该尽可能避免任何 apache tomcat 级别的更改。
以下是我们目前实现的内容:
- 我们尝试使用以下链接实现反向代理:https://github.com/mitre/HTTP-Proxy-Servlet
- 因此,基本原理是将第 3 方 url 调用为 web 服务并编辑 httpresponse 并将我们的域和上下文路径添加到作为响应接收的任何文件中的 url。虽然这不是一个好的解决方案并且会消耗大量时间和空间,但它确实可以完成工作。
我们面临的问题:
- 除 .net 应用程序中的 ajax 请求外,一切正常。
- 抛出的错误是:Sys.WebForms.PageRequestManagerParserErrorException:无法解析从服务器接收到的消息。此错误的常见原因是通过调用 Response.Write()、响应过滤器、HttpModules 或启用了服务器跟踪来修改响应。
这里是做httpresponse修改任务的代码片段:
protected void copyResponseEntity(HttpResponse proxyResponse, HttpServletResponse servletResponse,
HttpRequest proxyRequest, HttpServletRequest servletRequest)throws IOException {
HttpEntity entity = new BufferedHttpEntity(proxyResponse.getEntity());
if (entity.isChunked()) {
InputStream is = entity.getContent();
String proxyBody = EntityUtils.toString(entity);
proxyBody = proxyBody.replaceAll("/.netContextRoot/", "/ourContextRoot/.netContextRoot/");
InputStream stream = new ByteArrayInputStream(proxyBody.getBytes(StandardCharsets.UTF_8));
OutputStream os = servletResponse.getOutputStream();
byte[] buffer = new byte[10 * 1024];
int read;
while ((read = stream.read(buffer)) != -1) {
os.write(buffer, 0, read);
if (doHandleCompression || stream.available() == 0 /* next is.read will block */) {
os.flush();
}
}
// Entity closing/cleanup is done in the caller (#service)
} else {
String proxyBody = EntityUtils.toString(entity);
proxyBody = proxyBody.replaceAll("/.netContextRoot/", "/ourContextRoot/.netContextRoot/");
EntityUtils.updateEntity(proxyResponse, new StringEntity(proxyBody));
HttpEntity entity2 = proxyResponse.getEntity();
OutputStream servletOutputStream = servletResponse.getOutputStream();
entity2.writeTo(servletOutputStream);
}
}
任何人都可以帮助我们解决这种情况吗?另外,如果您有任何其他解决方案而不对 apache 级别进行任何更改,那么请提及。
提前致谢。
【问题讨论】:
-
你不能使用 iframe 吗?它仍然可以是您的应用程序并允许第 3 方显示该应用程序
-
如果您无法控制要求 3rd 方域甚至允许您的应用程序通过 IFrame 或类似要求访问它,那么您只剩下包装所有功能并在那个用户界面。其上的任何反向代理最终也会开始显示带有他们引入的安全层的阻止程序。想象一下,如果我们在任何银行域上做一个反向代理并在中间监听所有请求! (中间人)
-
我认为@NagarajTantri 在推荐 iframe 使用时有最好的方法; CORS 异常可以通过在您的终端或 apache 上传递 "allow cross domain" 来解决(您说您应该避免使用它,但并不是说它根本无法完成 - 如果没有,它将是一个单一的设置) t 为你工作)。
-
@SammuelMiranda 我认为他还提到他们无法在 3rd 方应用程序中更改 CORS 标头。考虑到必须为应该允许(第三方)的服务启用这些 CORS,这将再次成为一个问题。
-
如果您在上面包含的代码中遇到的唯一问题是来自客户端的特定类型请求的 c# 异常,那么我将通过尝试找出这些失败请求的原因来开始调试不同于上班族。我怀疑您的代码弄乱了一些请求并导致 c# 应用程序的行为不同。您可以使用 wireshark 分析请求和响应以查看差异。
标签: java .net proxy url-rewriting reverse-proxy