Java HTTPServer удостоверяване - страна на клиента

Внедрих много прост 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();
  }

}

person Samantha Catania    schedule 02.01.2015    source източник


Отговори (2)


Обикновено повечето хора биха използвали рамка за удостоверяване като Shiro или Spring Security.

Тези рамки регистрират Servlet филтър по шаблон, като /*, за да наложат удостоверяване на всички заявки. Те съхраняват данни за удостоверяване в сесията на Servlet, за да поддържат потребителите влезли между заявките, което обикновено се прави от HTTP сървъра имплицитно чрез бисквитки. Те също така регистрират специален контекст за приемане на заявки за удостоверяване, базирани на формуляр, като POST заявки към /login.

Тези крайни точки, базирани на формуляр, ще прочетат, обикновено application/x-www-form-urlencoded, заявка и ще изтеглят изпратените потребителско име и парола, ще хешират паролата по същия начин, по който сървърът съхранява паролата и ще ги сравняват, за да проверят принципалите за удостоверяване.

person Alex    schedule 02.01.2015
comment
Опитвах се да избегна Spring, тъй като изглеждаше малко прекалено за моя много прост проект, но в крайна сметка изглежда, че това е най-добрият ми избор - person Samantha Catania; 05.01.2015
comment
@SamanthaCatania, съгласен съм, ако се опитвате да го поддържате просто, отидете с Shiro, това е отлична рамка и не е необходимо да въвежда никакви допълнителни външни зависимости - person Alex; 05.01.2015
comment
Spring изглежда има повече поддръжка на браузър от страна на клиента или съм пропуснал нещо? - person Samantha Catania; 05.01.2015

Протоколът Basic Authentication гласи, че заявката на клиента трябва да има заглавка под формата на

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 в заявката. Стойността ще бъде Base64 кодиран низ от admin:password, който е 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=
person Community    schedule 03.01.2015
comment
Първоначалният въпрос гласи, че той има работещо основно удостоверяване и търсеше информация за това как работят влизанията, базирани на формуляри, което предполага използване на сесия и т.н. И това попада в категорията не изобретявайте колелото, тъй като рамки като Shiro или Spring Security са добре установени при поддържане на състояние на удостоверяване - person Alex; 03.01.2015
comment
@Alex вярно, може да съм го прочел погрешно или да съм го разбрал погрешно, но OP също не е посочил клиент. Доколкото знаем, това е приложение Swing, с което OP си играе. Има твърде много възможности. Но без да знам клиента, който OP възнамерява да използва, не мисля, че всеки отговор е просто някакви опции, хвърлени в стената, надявайки се да се задържи :-) Но изглежда сте прави за моето възможно неразбиране на въпроса. Можем да изчакаме разяснение от ОП - person Paul Samsotha; 03.01.2015