我在 tomcat 9(Linux 上)上部署了 jenkins.war,并將其配置為 http 和 https。
server.xml 上的配置
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/ssl/test.keystore"
type="RSA" certificateKeystorePassword="changeit"/>
</SSLHostConfig>
</Connector>
web.xml 上的配置
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPSOnly</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
當沒有托管 jenkins 時,我可以使用上面的 tomcat 配置將 http 重定向到 https。但是在部署 jenkins.war 后將 http 重定向到 https 不起作用。
jenkins 將 http 重定向到 https 是否需要任何其他配置更改?
uj5u.com熱心網友回復:
如果您將安全約束添加到“$CATALINA_BASE/conf/web.xml”,該約束將使用 Servlet 規范中定義的組合約束規則與 Web 應用程式中定義的任何約束組合。
Jenkins 默認定義了以下安全約束:
<security-constraint>
<web-resource-collection>
<web-resource-name>other</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<!-- no security constraint -->
</security-constraint>
Servlet 規范中的相關規則是:
The combination of user-data-constraints that apply to a common url-
pattern and http-method shall yield the union of connection types accepted by
the individual constraints as acceptable connection types. A security constraint that
does not contain a user-data-constraint shall combine with other user-data-
constraint to cause the unprotected connection type to be an accepted connection
type.
因此,Jenkins 規則與您的規則相結合,結果是允許不受保護的 (http) 連接。
可能的解決方案包括:
- 從 jenkins.war 中打包的 web.xml 檔案中移除安全約束
- 從 jenkins.war 中打包的 web.xml 檔案中編輯安全約束
- 部署自定義閥門或過濾器以強制重定向
uj5u.com熱心網友回復:
根據Mark Thomas 的回答中的注釋,我嘗試了兩種不同的方法,這兩種方法都對我有用。
這兩種方法還需要您在問題中已經描述的更改。
方法一
在 Jenkins WAR 中編輯安全約束。
為此,我讓 Tomcat 將webapps
目錄中的 WAR 炸開,然后在webapps/jenkins/WEB-INF/web.xml
. 我注釋掉了以下部分:
<!-- commented out this part...
<security-constraint>
<web-resource-collection>
<web-resource-name>other</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
-->
<!-- no security constraint -->
<!-- ...and this part </security-constraint> -->
方法二
我創建了一個 Tomcat Valve,我將它創建為一個 JAR 檔案,然后放在 Tomcat 的主lib
目錄中。
我在 Tomcat 中添加了一個閥門元件,以激活閥門。
具體步驟:
我使用了最新版本的 Jenkins LTS(長期支持)——版本 2.346.3。因為這個版本的 Jenkins 不支持
jakarta
包,所以我將它安裝在 Tomcat 9 上(用于javax
包)。我創建了一個標準的 Java 庫專案,它被打包到一個 JAR(不是 WAR)中。Maven POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ajames.tomcathttpsvalve</groupId>
<artifactId>TomcatHttpsValve</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<exec.mainClass>org.ajames.tomcathttpsvalve.TomcatHttpsValve</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>9.0.65</version>
</dependency>
</dependencies>
</project>
您可能需要針對您的 Java 版本調整編譯器設定。
- 我創建了以下閥門類:
package org.ajames.tomcathttpsvalve;
import java.io.IOException;
import javax.servlet.ServletException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
// In server.xml:
// <Valve className="org.ajames.tomcathttpsvalve.TomcatHttpsValve"
// fromPort="8080" toPort="8443" />
//
// This class is packaged as a JAR & placed in Tomcat's /lib
public class TomcatHttpsValve extends ValveBase {
private final String fromScheme = "http";
private final String toScheme = "https";
private final int httpsDefaultPort = 443;
private int fromPort; // see valve config for value
private int toPort; // see valve config for value
public TomcatHttpsValve() {
super(true); // async supported
}
@Override
public void invoke(Request req, Response resp) throws IOException, ServletException {
if (req.getScheme().toLowerCase().equals(toScheme)) {
// already using https:
getNext().invoke(req, resp);
} else {
// need to redirect to https:
resp.sendRedirect(buildNewReqUrl(req));
}
}
private String buildNewReqUrl(Request req) {
String scheme = req.getScheme();
int port = req.getServerPort();
if (scheme.toLowerCase().equals(fromScheme)) {
scheme = toScheme;
}
if (port == fromPort) {
port = toPort;
}
// build the new URL
// assumes no userinfo (...//john.doe@...)
StringBuilder sb = new StringBuilder();
sb.append(scheme).append("://").append(req.getServerName());
if (port != httpsDefaultPort) { // 443 is implicit with https
sb.append(":").append(port);
}
sb.append(req.getRequestURI()); // (e.g. /foo/bar)
if (req.getQueryString() != null) {
sb.append("?").append(req.getQueryString());
}
return sb.toString();
}
public int getFromPort() {
return fromPort;
}
public void setFromPort(String fromPort) {
this.fromPort = Integer.parseInt(fromPort);
}
public int getToPort() {
return toPort;
}
public void setToPort(String toPort) {
this.toPort = Integer.parseInt(toPort);
}
}
這會攔截請求 URL 并(如果需要)重定向到修改后的 URL。
我將包含此類的 JAR 檔案放在 Tomcat 主lib
目錄中。
- 我創建了一個新的閥元件:
<Valve className="org.ajames.tomcathttpsvalve.TomcatHttpsValve"
fromPort="8080" toPort="8443" />
就我而言,我選擇將此添加到<host>
我的 Tomcatserver.xml
檔案的部分。這意味著閥門適用于進入該主機的所有請求(在我的情況下,localhost
)。
<engine>
如果您想影響所有流量,也可以將其放在該部分中。
(如果您想要更精細的控制 - 對于特定的 Web 應用程式,您也可以將其放置在特定<context>
部分中。但這需要您自定義 Jenkins 安裝,類似于方法一。)
使用 Tomcat 閥將您與使用 Tomcat 作為 Jenkins 應用程式的容器聯系在一起。但是您不需要對 Jenkins 進行任何更改。
當然,您需要記住在升級 Tomcat 時重新應用這些自定義設定。jakarta
如果升級到 Tomcat 10 ,您還需要使用包而不是javax
包(使用相關版本的tomcat-catalina
依賴項)重新構建 Valve 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/506448.html