英文:
Configure JettyTestContainer with SSL for JerseyTest
问题
我被指派为团队的代码设置集成测试任务。这些测试需要对在Jersey 2.27中实现的REST端点执行HTTPS请求。在我寻找如何执行这种类型的测试时,我偶然发现了来自Baeldung的这篇文章,它指引我使用Jersey测试框架以及他们为此目的实现的提供者容器。考虑到我们的代码之前使用自定义的Jetty实例来执行这些操作,所以我选择了Jetty容器。我开始实现我们的测试,但在为将提供REST请求的JettyTestContainer配置SSL时遇到了困难。我收到了一个IllegalArgumentException,其中指出“在不使用SSL时,URI方案应为http”。我不知道如何继续了。
这是我的测试类:
public class ProjectTest extends JerseyTest {
private SSLContext sslCtx;
@Override
protected Application configure() {
ResourceConfig conf = new ResourceConfig(Sets.newHashSet(RestSuite1.class));
SslConfigurator sslConfig = SslConfigurator.newInstance()
.trustStoreFile()
.trustStorePassword()
.keyStoreFile()
.keyStorePassword();
sslCtx = sslConfig.createSSLContext();
}
@Override
public URI getBaseUri() {
return URI.create("https://localhost:1234");
}
@Override
public Client getClient() {
return ClientBuilder.newBuilder().sslContext(sslCtx).build();
}
@Test
public void test1() throws Exception {
String testString = "HelloWorld";
OurObject oo = target("/restSuite1")
.request()
.post(Entity.entity(testString, MediaType.APPLICATION_JSON), String.class);
}
}
这是RestSuite1:
@Path("restSuite1")
@Produces("application/json")
public class RestSuite1 {
@POST
@Consumes("application/json")
@Produces("application/json")
public String doSomething(String payload) {
// Do Something
}
}
这是我的pom.xml:
<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>com.sample</groupId>
<artifactId>my-application1</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>my war</name>
<url>http://some-url.com</url>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<!-- 其他依赖... -->
</dependencies>
</project>
需要注意的是,在尝试SSL配置之前,我能够成功访问POST /restSuite1端点。
我找到了这个问题,但它似乎不是在JerseyTest场景中使用的Grizzly SSL配置。
我找到了这个问题,但它似乎是设置用户角色而不是实际的SSL配置。
然后我找到了这个问题,提问者似乎有与我相同的问题,然而没有人回答这个问题。
请帮助!
英文:
I've been tasked with setting up integration tests for my team's code. These tests will require performing HTTPS requests to REST endpoints implemented in Jersey 2.27. In my search for how to perform this kind of test, I stumbled upon this article from Baeldung that pointed me to the Jersey Test Framework and the provider containers they've implemented for this purpose. I chose the Jetty container, as our code was using a 'roll your own' Jetty instance to do all this. I began the implementation of our tests, and ran into difficulty configuring SSL for the JettyTestContainer that would serve up the rest requests. I began receiving an IllegalArgumentException stating that "The URI scheme should be http when not using SSL." I'm at a loss for how to proceed.
Here's my test class:
public class ProjectTest extends JerseyTest {
private SSLContext sslCtx;
@Override
protected Application configure() {
ResourceConfig conf = new ResourceConfig(Sets.newHashSet(RestSuite1.class));
SslConfigurator sslConfig = SslConfigurator.newInstance()
.trustStoreFile()
.trustStorePassword()
.keyStoreFile()
.keyStorePassword()
sslCtx = sslConfig.createSSLContext();
}
@Override
public URI getBaseUri() {
return URI.create("https://localhost:1234")
}
@Override
public Client getClient() {
return ClientBuilder.newBuilder().sslContext(sslCtx).build();
}
@Test
public void test1() throws Exception {
String testString = "HelloWorld";
OurObject oo = target("/restSuite1")
.request()
.post(Entity.entity(testString, MediaType.APPLICATION_JSON), String.class);
}
}
Here's a RestSuite1:
@Path("restSuite1")
@Produces("application/json")
public class RestSuite1 {
@POST
@Consumes("application/json")
@Produces("application/json")
public String doSomething(String payload) {
// Do Something
}
}
Here's my pom.xml:
<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>com.sample</groupId>
<artifactId>my-application1</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>my war</name>
<url>http://some-url.com</url>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
I should note that prior to attempting the SSL configuration, I was able to reach the POST /restSuite1 end point successfully.
I found this question, but it doesn't look like a Grizzly SSL configuration one would use in a
JerseyTest scenario.
I found this question, but it looks like setting user roles and not an actual SSL configuration.
I then found this question, and the person that asked it seems to have the same problem I do, however no one ever answered the question.
Please help!
答案1
得分: 2
好的,以下是翻译好的内容:
看起来在JerseyTest中没有这个选项。我创建了一个拉取请求来添加这个选项。请在这里查看:https://github.com/eclipse-ee4j/jersey/pull/4573。我不太确定他们会以多快的速度批准和发布它...
我知道这不是你要找的答案...然而,如果你仍然想要配置你的服务器使用SSL,并且在等待拉取请求被批准之前测试你的应用程序使用HTTPS,你可以查看我的GitHub项目,其中有一个使用Grizzly而不是JerseyTest进行测试的基本示例:Application 和 IntegrationTest
=============== 更新 #1 20-12-2020 ===============
拉取请求已被批准、合并并发布。从版本2.33开始就可以使用了。现在可以通过提供带有sslparameters的sslcontext来配置你的Jersey测试。一个示例设置如下:
public class SecuredJerseyTest extends JerseyTest {
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyTestContainerFactory();
}
@Path("hello")
public static class TestResource {
@GET
public String hello() {
return "hello";
}
}
@Override
protected Application configure() {
return new ResourceConfig(TestResource.class);
}
@Override
protected URI getBaseUri() {
return UriBuilder
.fromUri("https://localhost")
.port(getPort())
.build();
}
@Override
protected Optional<SSLContext> getSslContext() {
SSLContext sslContext = ... // 你初始化的服务器 sslContext
return Optional.of(sslContext);
}
@Override
protected Optional<SSLParameters> getSslParameters() {
serverSslParameters = new SSLParameters();
serverSslParameters.setNeedClientAuth(false);
return Optional.of(serverSslParameters);
}
@Test
public void testHello() {
SSLContext sslContext = ... // 你初始化的客户端 sslContext
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.build();
WebTarget target = client.target(getBaseUri()).path("hello");
String s = target.request().get(String.class);
Assert.assertEquals("hello", s);
}
}
英文:
It looks like this option is not available within JerseyTest. I created a pull request to add this option. Please have a look here: https://github.com/eclipse-ee4j/jersey/pull/4573 I am not quite sure how fast they will approve and publish it...
I know it was not the answer you are looking for... However if you still want to configure your server with ssl and test your application with https without waiting till the pull request got approved, you can have a look at my github project which has a basic example of testing a jersey server with grizzly without JerseyTest: Application & IntegrationTest
=============== UPDATE #1 20-12-2020 ===============
The pull request has been approved, merged and released. It is now available starting from version 2.33. It is now possible to provide a sslcontext with sslparameters to configure your jersey test. An example setup would be:
public class SecuredJerseyTest extends JerseyTest {
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyTestContainerFactory();
}
@Path("hello")
public static class TestResource {
@GET
public String hello() {
return "hello";
}
}
@Override
protected Application configure() {
return new ResourceConfig(TestResource.class);
}
@Override
protected URI getBaseUri() {
return UriBuilder
.fromUri("https://localhost")
.port(getPort())
.build();
}
@Override
protected Optional<SSLContext> getSslContext() {
SSLContext sslContext = ... // your initialised server sslContext
return Optional.of(sslContext);
}
@Override
protected Optional<SSLParameters> getSslParameters() {
serverSslParameters = new SSLParameters();
serverSslParameters.setNeedClientAuth(false);
return Optional.of(serverSslParameters);
}
@Test
public void testHello() {
SSLContext sslContext = ... // your initialised client sslContext
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.build();
WebTarget target = client.target(getBaseUri()).path("hello");
String s = target.request().get(String.class);
Assert.assertEquals("hello", s);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论