簡體   English   中英

Java HTTPServer身份驗證-客戶端

[英]Java HTTPServer Authentication - Client Side

我實現了一個非常簡單的HTTP服務器的描述在這里 我設法通過使用Authentication頭使身份驗證正常工作,但是我無法弄清楚如何從表單中獲取憑據並使用它們對服務器進行身份驗證。 通常如何做?

碼:

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();
  }

}

通常,大多數人會使用Shiro或Spring Security等身份驗證框架。

這些框架在模式(例如/*上注冊Servlet過濾器,以對所有請求強制執行身份驗證。 它們將身份驗證數據存儲在Servlet會話中,以使用戶在兩次請求之間登錄,這通常由HTTP服務器通過Cookies隱式完成。 他們還注冊了一個特殊的上下文來接受基於表單的身份驗證請求,例如對/login POST請求。

這些基於表單的終結點通常會讀取application/x-www-form-urlencoded ,請求並提取提交的用戶名和密碼,以與服務器存儲密碼相同的方式對密碼進行哈希處理,並比較它們以驗證身份驗證主體。

基本身份驗證協議規定客戶端請求應具有以下形式的標頭:

Authorization: Basic Base64Encoded(username:password)

其中Base64Encoded(username:password)是的實際Base64編碼串username:password 例如,如果我的用戶名和密碼是peeskillet:pass ,則標題應發送為

Authorization: Basic cGVlc2tpbGxldDpwYXNz

鏈接的示例中 ,它使用的是基本身份驗證。 受保護資源的URL是

http://localhost:8000/get

您可以轉到瀏覽器中的URL,然后將看到一個對話框(在Firefox中),如該答案所示 輸入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=

對於其他組合,您可以直接在此處鍵入組合,或者Java 8具有java.util.Base64類,可用於對憑據進行編碼

String cred = "admin:password";
String encoded = Base64.getEncoder().encodeToString(cred.getBytes());
System.out.println(encoded);
// YWRtaW46cGFzc3dvcmQ=

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM