我有一个Java web应用程序,托管在Amazon web Services上,它运行在退役的Tomcat 8和Amazon Linux上。
我尝试创建一个新环境来测试在最新的Tomcat 8.5和Corretto 11上运行在Amazon Linux 2上的应用程序。
在这个过程中,我遇到了一个大问题,在我的应用程序中,它使用一个基础URL,例如https://myserver.com,它正在做一些字符串连接来添加路径,例如/rest/myendpoint,当然应该解析为
https://myserver.com/rest/myendpoint
但不幸的是,它在不知不觉中被c#的new URL()
传递,它在连接之前附加了一个尾斜杠。
https://myserver.com/rest/myendpoint
作为
发送到服务器https://myserver.com/rest//myendpoint
(注意rest//
应为rest/
)
在将Java war文件部署到新环境后,来自应用程序的一些请求以404失败。我分析了这些网络日志,当然是所有路径中有双转义的url。
作为在Postman中编写请求具有单个斜杠工作良好的测试,双引号在HTTP 404中失败,就像应用程序一样。
现在的问题是,应用程序已经在使用,我们不能改变应用程序,因为这将涉及到一个很长的延迟(构建,应用商店审批过程,然后等待每个人升级应用程序),最可能是几个月。
我在AWS门户中找不到任何东西来配置这个
我确实尝试切换到Nginx,但我遇到了同样的错误。
我确实看到一些人提到使用。eb-extensions,但是整个apache重写/mod规则对我来说非常陌生。实际上,我想将http://或https://之后的任何双斜杠重写为单斜杠。你能就如何做到这一点提出建议吗?
我正在使用Tomcat的Elastic Beanstalk(目前由Apache支持)和最新的Tomcat平台版本- Tomcat 8.5和Corretto 11运行在64位Amazon Linux 2上。
谢谢。
因为我真的不想在. ebeextensions上瞎折腾,所以我扩展了一个现有的servlet过滤器(链中最早的过滤器)来检查路径。然后我就可以使用调度器转发了,它工作得很好。
虽然我确信我可以用regi -ex做一些更干净的事情,但这对我来说是可行的,我可以先用Postman在本地测试它。
package com.devology.servlet.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class AuthenticationFilter implements Filter {
public AuthenticationFilter() {
}
private boolean doBeforeProcessing(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
HttpServletRequest hsr = (HttpServletRequest) request;
final String path = hsr.getServletPath();
String fullUrl = hsr.getRequestURL().toString();
String remoteAddress = hsr.getRemoteAddr();
// Example URL from bad app...
//
// http://localhost:8084/MyApp//rest/login
//
// path = /rest
// fullUrl = http://localhost:8084/MyApp//rest/login
// indexOfPath = ^ = 34
//
// If the character before the start of the path is also a slash then
// we need to internally forward
int indexOfPath = fullUrl.indexOf(path + "/");
boolean needsUrlRewrite = false;
if (indexOfPath != -1) {
String previousCharacter = fullUrl.substring(indexOfPath - 1, indexOfPath);
needsUrlRewrite = "/".equals(previousCharacter);
}
if (needsUrlRewrite) {
// Just take the path from the point of indexOfPath, .e.g /rest/login
String rewrittenPath = fullUrl.substring(indexOfPath);
RequestDispatcher dispatcher = request.getServletContext().getRequestDispatcher(rewrittenPath);
dispatcher.forward(request, response);
return false;
}
// Any other checks like authorisation, or return true to let all through
return true;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
if (doBeforeProcessing(request, response)) {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig fc) throws ServletException {
// Your Init
}
@Override
public void destroy() {
// Your cleanup
}
}
这假设你已经在web.xml中像这样配置了…
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>com.devology.servlet.filters.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<error-page>
<error-code>500</error-code>
<location>/error-500.html</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error-404.html</location>
</error-page>
</web-app>
我没有解决。ebeextensions和Apache配置的问题,因为我真的不知道我在做什么,上面的servlet过滤器做了我所需要的。