Reputation: 5316
I Implemented a very simple HTTP Server as described here. I managed to get the authentication working by using the Authentication header but I cannot figure out how to take the credentials from a form and use them to authenticate with the server. How is this usually done?
Code:
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.BasicAuthenticator;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class SimpleHttpServer3 {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/info", new InfoHandler());
HttpContext hc1 = server.createContext("/get", new GetHandler());
hc1.setAuthenticator(new BasicAuthenticator("get") {
@Override
public boolean checkCredentials(String user, String pwd) {
return user.equals("admin") && pwd.equals("password");
}
});
server.setExecutor(null); // creates a default executor
server.start();
System.out.println("The server is running");
}
// http://localhost:8000/info
static class InfoHandler implements HttpHandler {
public void handle(HttpExchange httpExchange) throws IOException {
String response = "Use /get to authenticate (user:admin pwd:password)";
SimpleHttpServer3.writeResponse(httpExchange, response.toString());
}
}
static class GetHandler implements HttpHandler {
public void handle(HttpExchange httpExchange) throws IOException {
StringBuilder response = new StringBuilder();
response.append("<html><body>");
response.append("hello " + httpExchange.getPrincipal().getUsername());
response.append("</body></html>");
SimpleHttpServer3.writeResponse(httpExchange, response.toString());
}
}
public static void writeResponse(HttpExchange httpExchange, String response) throws IOException {
httpExchange.sendResponseHeaders(200, response.length());
OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
Upvotes: 2
Views: 2914
Reputation: 209072
Basic Authentication protocol states the client request should have a header in the form of
Authorization: Basic Base64Encoded(username:password)
where Base64Encoded(username:password)
is an actual Base64 encoded string of the username:password
. For example, if my username and password are peeskillet:pass
, the header should be sent out as
Authorization: Basic cGVlc2tpbGxldDpwYXNz
In the example from your link, it's using Basic authentication. The URL to the protected resource is
http://localhost:8000/get
You can go to your browser to the URL, and you will see a dialog (in Firefox) as seen in this answer. Enter admin
(username) and password
(password). You will get the hello admin
return message.
You don't need to do any authentication yourself (or parsing/decoding at least), as internally (I haven't checked the source code, but it seems to be the case) the BasicAuthenticator
decodes and parses the Authorization
header and passes the username and password to the checkCredentials
method that you implements. Since it simple only allows admin/password
, that is the only combination that will authenticate.
Just for completeness, the decoding/parsing (in pseudo-code) might look something like
String authHeader = request.getHeader("Authorization");
String[] split = authHeader.split("\\s");
String credentials = split[1];
String decoded = Base64.decode(credentials);
String[] userPass = decoded.split(":");
String username = userPass[0];
String password = userPass[1];
boolean authenticated = checkCredentials(username, password);
If you want to try and make a request with code, then you would need to set the Authorization
header in the request. The value would be a Base64 encoded string of admin:password
, which is YWRtaW46cGFzc3dvcmQ=
. So the header should be sent out as
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
For other combinations, you can just go here to type in the combinations, or Java 8 has the java.util.Base64 class that you can use to encode the credentials
String cred = "admin:password";
String encoded = Base64.getEncoder().encodeToString(cred.getBytes());
System.out.println(encoded);
// YWRtaW46cGFzc3dvcmQ=
Upvotes: -1
Reputation: 2485
Typically most people would use an authentication framework like Shiro or Spring Security.
These frameworks register a Servlet filter on a pattern, such as /*
to enforce authentication on all requests. They store authentication data in the Servlet session to keep users logged in between requests, which is usually done by the HTTP server implicitly via Cookies. They also register a special context to accept form based authentication requests, such as POST requests to /login
.
These form based endpoints will read, typically a application/x-www-form-urlencoded
, request and pull out the submitted username and password, hash the password the same way that the server stores the password and compare them to verify the authentication principals.
Upvotes: 2