1/*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 8087112
27 * @modules jdk.incubator.httpclient
28 *          jdk.httpserver
29 * @run main/othervm BasicAuthTest
30 * @summary Basic Authentication Test
31 */
32
33import com.sun.net.httpserver.BasicAuthenticator;
34import com.sun.net.httpserver.HttpContext;
35import com.sun.net.httpserver.HttpExchange;
36import com.sun.net.httpserver.HttpHandler;
37import com.sun.net.httpserver.HttpServer;
38import java.io.IOException;
39import java.io.InputStream;
40import java.io.OutputStream;
41import java.net.InetSocketAddress;
42import java.net.PasswordAuthentication;
43import java.net.URI;
44import jdk.incubator.http.*;
45import java.util.concurrent.ExecutorService;
46import java.util.concurrent.Executors;
47import static java.nio.charset.StandardCharsets.US_ASCII;
48import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString;
49import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
50
51public class BasicAuthTest {
52
53    static volatile boolean ok;
54    static final String RESPONSE = "Hello world";
55    static final String POST_BODY = "This is the POST body 123909090909090";
56
57    public static void main(String[] args) throws Exception {
58        HttpServer server = HttpServer.create(new InetSocketAddress(0), 10);
59        ExecutorService e = Executors.newCachedThreadPool();
60        Handler h = new Handler();
61        HttpContext serverContext = server.createContext("/test", h);
62        int port = server.getAddress().getPort();
63        System.out.println("Server port = " + port);
64
65        ClientAuth ca = new ClientAuth();
66        ServerAuth sa = new ServerAuth("foo realm");
67        serverContext.setAuthenticator(sa);
68        server.setExecutor(e);
69        server.start();
70        HttpClient client = HttpClient.newBuilder()
71                                      .authenticator(ca)
72                                      .build();
73
74        try {
75            URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo");
76            HttpRequest req = HttpRequest.newBuilder(uri).GET().build();
77
78            HttpResponse resp = client.send(req, asString());
79            ok = resp.statusCode() == 200 && resp.body().equals(RESPONSE);
80
81            if (!ok || ca.count != 1)
82                throw new RuntimeException("Test failed");
83
84            // repeat same request, should succeed but no additional authenticator calls
85
86            resp = client.send(req, asString());
87            ok = resp.statusCode() == 200 && resp.body().equals(RESPONSE);
88
89            if (!ok || ca.count != 1)
90                throw new RuntimeException("Test failed");
91
92            // try a POST
93
94            req = HttpRequest.newBuilder(uri)
95                             .POST(fromString(POST_BODY))
96                             .build();
97            resp = client.send(req, asString());
98            ok = resp.statusCode() == 200;
99
100            if (!ok || ca.count != 1)
101                throw new RuntimeException("Test failed");
102        } finally {
103            server.stop(0);
104            e.shutdownNow();
105        }
106        System.out.println("OK");
107    }
108
109    static class ServerAuth extends BasicAuthenticator {
110
111        ServerAuth(String realm) {
112            super(realm);
113        }
114
115        @Override
116        public boolean checkCredentials(String username, String password) {
117            if (!"user".equals(username) || !"passwd".equals(password)) {
118                return false;
119            }
120            return true;
121        }
122
123    }
124
125    static class ClientAuth extends java.net.Authenticator {
126        volatile int count = 0;
127
128        @Override
129        protected PasswordAuthentication getPasswordAuthentication() {
130            count++;
131            return new PasswordAuthentication("user", "passwd".toCharArray());
132        }
133    }
134
135   static class Handler implements HttpHandler {
136        static volatile boolean ok;
137
138        @Override
139        public void handle(HttpExchange he) throws IOException {
140            String method = he.getRequestMethod();
141            InputStream is = he.getRequestBody();
142            if (method.equalsIgnoreCase("POST")) {
143                String requestBody = new String(is.readAllBytes(), US_ASCII);
144                if (!requestBody.equals(POST_BODY)) {
145                    he.sendResponseHeaders(500, -1);
146                    ok = false;
147                } else {
148                    he.sendResponseHeaders(200, -1);
149                    ok = true;
150                }
151            } else { // GET
152                he.sendResponseHeaders(200, RESPONSE.length());
153                OutputStream os = he.getResponseBody();
154                os.write(RESPONSE.getBytes(US_ASCII));
155                os.close();
156                ok = true;
157            }
158        }
159
160   }
161}
162