我实现了一个非常简单的HTTP服务器所描述的here。我设法得到认证通过使用认证头工作,但我无法弄清楚如何从一个形式采取的凭据,并利用它们与服务器进行身份验证。这是如何做到一般?
码:
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();
}
}
通常,大多数人会使用像四郎或Spring Security的验证框架。
这些框架上的图案注册一个Servlet过滤器,如/*
执行关于所有请求认证。它们存储在Servlet会话的认证数据,保证用户的请求,这通常是由HTTP服务器通过cookie完成隐含之间登录。他们还注册一个特殊的背景下接受基于表单的身份验证请求,如POST请求/login
。
这些形式的基于端点会读,通常是application/x-www-form-urlencoded
,要求并拉出提交的用户名和密码,散列密码相同的方式,服务器存储的密码,并加以比较,以验证认证校长。
Basic Authentication协议状态的客户端请求应具有的形式的标题
Authorization: Basic Base64Encoded(username:password)
其中Base64Encoded(username:password)
是编码的username:password
的串的实际的Base64。例如,如果我的用户名和密码peeskillet:pass
,标题应该送出了
Authorization: Basic cGVlc2tpbGxldDpwYXNz
在the example from your link,它使用基本身份验证。该网址到受保护的资源
http://localhost:8000/get
你可以到你的浏览器的网址,你会看到一个对话框(在Firefox)在this answer看到。输入admin
(用户名)和password
(密码)。您将得到hello admin
返回消息。
你不需要做任何自己的身份验证(或至少解析/解码),作为内部(我没有检查的源代码,但它似乎是这样)的BasicAuthenticator
解码和解析Authorization
头和传递用户名和密码,你实现checkCredentials
方法。由于它简单的只允许admin/password
,那就是将要验证的唯一组合。
只是为了完整性,解码/解析(伪代码)可能看起来像
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);
如果您想尝试,并与代码的请求,那么你就需要设置Authorization
头中的请求。该值将是admin:password
的Base64编码字符串,它是YWRtaW46cGFzc3dvcmQ=
。因此,头部应该送出了
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
对于其他的组合,你可以在go here键入组合,或Java 8具有您可以使用编码凭据java.util.Base64类
String cred = "admin:password";
String encoded = Base64.getEncoder().encodeToString(cred.getBytes());
System.out.println(encoded);
// YWRtaW46cGFzc3dvcmQ=