1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.testing.classic;
29
30 import static org.hamcrest.MatcherAssert.assertThat;
31
32 import java.nio.charset.StandardCharsets;
33 import java.util.Random;
34
35 import org.apache.hc.core5.http.ClassicHttpRequest;
36 import org.apache.hc.core5.http.ClassicHttpResponse;
37 import org.apache.hc.core5.http.ContentType;
38 import org.apache.hc.core5.http.HttpEntity;
39 import org.apache.hc.core5.http.HttpException;
40 import org.apache.hc.core5.http.HttpHeaders;
41 import org.apache.hc.core5.http.HttpHost;
42 import org.apache.hc.core5.http.HttpResponse;
43 import org.apache.hc.core5.http.HttpStatus;
44 import org.apache.hc.core5.http.HttpVersion;
45 import org.apache.hc.core5.http.Method;
46 import org.apache.hc.core5.http.URIScheme;
47 import org.apache.hc.core5.http.impl.bootstrap.HttpRequester;
48 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
49 import org.apache.hc.core5.http.impl.bootstrap.StandardFilter;
50 import org.apache.hc.core5.http.io.SocketConfig;
51 import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
52 import org.apache.hc.core5.http.io.entity.EntityUtils;
53 import org.apache.hc.core5.http.io.entity.StringEntity;
54 import org.apache.hc.core5.http.io.support.AbstractHttpServerAuthFilter;
55 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
56 import org.apache.hc.core5.http.protocol.HttpContext;
57 import org.apache.hc.core5.http.protocol.HttpCoreContext;
58 import org.apache.hc.core5.net.URIAuthority;
59 import org.apache.hc.core5.testing.classic.extension.HttpRequesterResource;
60 import org.apache.hc.core5.testing.classic.extension.HttpServerResource;
61 import org.apache.hc.core5.util.Timeout;
62 import org.hamcrest.CoreMatchers;
63 import org.junit.jupiter.api.Test;
64 import org.junit.jupiter.api.extension.RegisterExtension;
65
66 public abstract class ClassicAuthenticationTest {
67
68 private static final Timeout TIMEOUT = Timeout.ofMinutes(1);
69
70 @RegisterExtension
71 private HttpServerResource serverResource;
72 @RegisterExtension
73 private HttpRequesterResource clientResource;
74
75 public ClassicAuthenticationTest(final Boolean respondImmediately) {
76 this.serverResource = new HttpServerResource(URIScheme.HTTP, bootstrap -> bootstrap
77 .setSocketConfig(
78 SocketConfig.custom()
79 .setSoTimeout(TIMEOUT)
80 .build())
81 .register("*", new EchoHandler())
82 .replaceFilter(StandardFilter.EXPECT_CONTINUE.name(), new AbstractHttpServerAuthFilter<String>(respondImmediately) {
83
84 @Override
85 protected String parseChallengeResponse(
86 final String challenge, final HttpContext context) throws HttpException {
87 return challenge;
88 }
89
90 @Override
91 protected boolean authenticate(
92 final String challengeResponse,
93 final URIAuthority authority,
94 final String requestUri,
95 final HttpContext context) {
96 return challengeResponse != null && challengeResponse.equals("let me pass");
97 }
98
99 @Override
100 protected String generateChallenge(
101 final String challengeResponse,
102 final URIAuthority authority,
103 final String requestUri,
104 final HttpContext context) {
105 return "who goes there?";
106 }
107
108 @Override
109 protected HttpEntity generateResponseContent(final HttpResponse unauthorized) {
110 return new StringEntity("You shall not pass!!!");
111 }
112 })
113 );
114 this.clientResource = new HttpRequesterResource(bootstrap -> bootstrap
115 .setSocketConfig(SocketConfig.custom()
116 .setSoTimeout(TIMEOUT)
117 .build())
118 );
119 }
120
121 @Test
122 public void testGetRequestAuthentication() throws Exception {
123 final HttpServer server = serverResource.start();
124 final HttpRequester requester = clientResource.start();
125
126 final HttpHost target = new HttpHost("localhost", server.getLocalPort());
127 final HttpCoreContext context = HttpCoreContext.create();
128 final ClassicHttpRequest request1 = new BasicClassicHttpRequest(Method.GET, "/stuff");
129 try (final ClassicHttpResponse response1 = requester.execute(target, request1, TIMEOUT, context)) {
130 assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_UNAUTHORIZED));
131 final String body1 = EntityUtils.toString(response1.getEntity());
132 assertThat(body1, CoreMatchers.equalTo("You shall not pass!!!"));
133 }
134 final ClassicHttpRequest request2 = new BasicClassicHttpRequest(Method.GET, "/stuff");
135 request2.setHeader(HttpHeaders.AUTHORIZATION, "let me pass");
136 try (final ClassicHttpResponse response2 = requester.execute(target, request2, TIMEOUT, context)) {
137 assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
138 final String body1 = EntityUtils.toString(response2.getEntity());
139 assertThat(body1, CoreMatchers.equalTo(""));
140 }
141 }
142
143 @Test
144 public void testPostRequestAuthentication() throws Exception {
145 final HttpServer server = serverResource.start();
146 final HttpRequester requester = clientResource.start();
147
148 final HttpHost target = new HttpHost("localhost", server.getLocalPort());
149 final HttpCoreContext context = HttpCoreContext.create();
150 final Random rnd = new Random();
151 final byte[] stuff = new byte[10240];
152 for (int i = 0; i < stuff.length; i++) {
153 stuff[i] = (byte) ('a' + rnd.nextInt(10));
154 }
155 final ClassicHttpRequest request1 = new BasicClassicHttpRequest(Method.POST, "/stuff");
156 request1.setEntity(new ByteArrayEntity(stuff, ContentType.TEXT_PLAIN));
157 try (final ClassicHttpResponse response1 = requester.execute(target, request1, TIMEOUT, context)) {
158 assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_UNAUTHORIZED));
159 final String body1 = EntityUtils.toString(response1.getEntity());
160 assertThat(body1, CoreMatchers.equalTo("You shall not pass!!!"));
161 }
162 final ClassicHttpRequest request2 = new BasicClassicHttpRequest(Method.POST, "/stuff");
163 request2.setHeader(HttpHeaders.AUTHORIZATION, "let me pass");
164 request2.setEntity(new ByteArrayEntity(stuff, ContentType.TEXT_PLAIN));
165 try (final ClassicHttpResponse response2 = requester.execute(target, request2, TIMEOUT, context)) {
166 assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
167 final String body1 = EntityUtils.toString(response2.getEntity());
168 assertThat(body1, CoreMatchers.equalTo(new String(stuff, StandardCharsets.US_ASCII)));
169 }
170 }
171
172 @Test
173 public void testPostRequestAuthenticationNoExpectContinue() throws Exception {
174 final HttpServer server = serverResource.start();
175 final HttpRequester requester = clientResource.start();
176
177 final HttpHost target = new HttpHost("localhost", server.getLocalPort());
178 final HttpCoreContext context = HttpCoreContext.create();
179 final Random rnd = new Random();
180 final byte[] stuff = new byte[10240];
181 for (int i = 0; i < stuff.length; i++) {
182 stuff[i] = (byte) ('a' + rnd.nextInt(10));
183 }
184 final ClassicHttpRequest request1 = new BasicClassicHttpRequest(Method.POST, "/stuff");
185 request1.setVersion(HttpVersion.HTTP_1_0);
186 request1.setEntity(new ByteArrayEntity(stuff, ContentType.TEXT_PLAIN));
187 try (final ClassicHttpResponse response1 = requester.execute(target, request1, TIMEOUT, context)) {
188 assertThat(response1.getCode(), CoreMatchers.equalTo(HttpStatus.SC_UNAUTHORIZED));
189 final String body1 = EntityUtils.toString(response1.getEntity());
190 assertThat(body1, CoreMatchers.equalTo("You shall not pass!!!"));
191 }
192 final ClassicHttpRequest request2 = new BasicClassicHttpRequest(Method.POST, "/stuff");
193 request2.setHeader(HttpHeaders.AUTHORIZATION, "let me pass");
194 request2.setVersion(HttpVersion.HTTP_1_0);
195 request2.setEntity(new ByteArrayEntity(stuff, ContentType.TEXT_PLAIN));
196 try (final ClassicHttpResponse response2 = requester.execute(target, request2, TIMEOUT, context)) {
197 assertThat(response2.getCode(), CoreMatchers.equalTo(HttpStatus.SC_OK));
198 final String body1 = EntityUtils.toString(response2.getEntity());
199 assertThat(body1, CoreMatchers.equalTo(new String(stuff, StandardCharsets.US_ASCII)));
200 }
201 }
202
203 }