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