我正在尝试最小化我的webapp的配置,我要删除的一件事就是端口号映射:
由于配置已经存在于conf / server.xml中,我不想在我的应用程序中复制这些设置。必须改变(并记住改变)多个配置文件是一件痛苦的事。此外,只要它支持http和https,应用程序就不应该关心它所部署的环境/容器。
我在web.xml中配置了以下内容,但除了重定向之外,我还需要能够构建https URL:
<security-constraint>
<web-resource-collection>
<web-resource-name>secure</web-resource-name>
<url-pattern>/https/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
上面的块告诉servlet容器将http请求重定向到其https对应项。显然,Tomcat知道请求来自哪个连接器,在server.xml中查找该连接器的“redirectPort”属性,并使用它构建https URL。
根据这些先前/相关的问题,似乎没有标准或特定于tomcat的方式来获取请求的相应https端口:
TL; DR:我的问题是,如果没有在您的网络应用中明确配置它们,您有什么想法来获取不安全请求的相应https端口号?
我的一个想法是使用与当前请求相同的端口号从webapp到其自身的http调用到安全约束后面的路径,并从响应中解析重定向位置。当然,应该缓存响应。有更简单的方法吗?
编辑:添加了answer代码。
答案 0 :(得分:1)
如果有人想知道如何实现我在问题中提供的想法,这里有一些示例代码,我将它们放在一起进行测试。我不认为我会使用这个解决方案。
这适用于问题正文中的安全约束块。
private static final String HTTPS_CONSTRAINED_PATH = "/https";
private static ConcurrentHashMap<String, Integer> resolvedHttpsPortMap = new ConcurrentHashMap<String, Integer>();
private static final ReentrantLock portMapLock = new ReentrantLock();
public static int resolveHttpsPort(HttpServletRequest request) {
if (request.isSecure()) return request.getServerPort();
String key = request.getServerName() + ":" + request.getServerPort();
Integer port = resolvedHttpsPortMap.get(key);
if (port == null) {
portMapLock.lock();
try {
port = resolvedHttpsPortMap.get(key);
if (port == null) {
URL url = new URL(request.getScheme(), request.getServerName(), request.getServerPort(), request.getContextPath() + HTTPS_CONSTRAINED_PATH);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() != 301 && conn.getResponseCode() != 302
&& conn.getResponseCode() != 303 && conn.getResponseCode() != 307) {
throw new IllegalStateException("Got unexpected response code " + conn.getResponseCode() + " from URL: " + url);
}
String location = conn.getHeaderField("Location");
if (location == null) {
throw new IllegalStateException("Did not get a Location header in the response from URL: " + url);
}
URL locationUrl = new URL(location);
port = locationUrl.getPort();
}
} catch (Exception e) {
logger.warn("Could not determine corresponding HTTPS port for '" + key + "'", e);
} finally {
if (port == null) port = -1;
resolvedHttpsPortMap.put(key, port);
portMapLock.unlock();
}
}
return port;
}
答案 1 :(得分:-1)
我不明白为什么你需要知道安全端口号。如果被访问的资源被标记为需要SSL,则Tomcat将重定向发送到https:和相应的安全端口。这就是server.xml中的配置。