我实现了一个非常简单的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();
}
}
答案 0 :(得分:1)
通常,大多数人会使用像Shiro或Spring Security这样的身份验证框架。
这些框架在模式上注册Servlet过滤器,例如/*
,以对所有请求强制执行身份验证。它们将身份验证数据存储在Servlet会话中,以保持用户在请求之间登录,这通常由HTTP服务器通过Cookie隐式完成。他们还注册了一个特殊的上下文来接受基于表单的身份验证请求,例如对/login
的POST请求。
这些基于表单的端点将读取(通常是application/x-www-form-urlencoded
个请求,并提取提交的用户名和密码,以与服务器存储密码相同的方式对密码进行散列,并将它们进行比较以验证身份验证主体。< / p>
答案 1 :(得分:0)
Basic Authentication协议规定客户端请求应具有
形式的标头Authorization: Basic Base64Encoded(username:password)
其中Base64Encoded(username:password)
是username:password
的实际Base64编码字符串。例如,如果我的用户名和密码是peeskillet:pass
,则标题应该以
Authorization: Basic cGVlc2tpbGxldDpwYXNz
在the example from your link中,它使用基本身份验证。受保护资源的URL是
http://localhost:8000/get
您可以访问浏览器访问该网址,然后您会在this answer中看到一个对话框(在Firefox中)。输入admin
(用户名)和password
(密码)。您将收到hello admin
返回消息。
您不需要自己进行任何身份验证(或至少解析/解码),因为内部(我还没有检查过源代码,但似乎是这种情况){{3解码并解析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=
对于其他组合,您只需BasicAuthenticator
键入组合,或者Java 8具有可用于编码凭据的go here类
String cred = "admin:password";
String encoded = Base64.getEncoder().encodeToString(cred.getBytes());
System.out.println(encoded);
// YWRtaW46cGFzc3dvcmQ=