2012-03-13 13 views
11

Mam następujący scenariusz:W jaki sposób można uwierzytelnić przy użyciu klienta Jersey na serwerze obsługującym JAAS?

Serwer: Jetty (ze skonfigurowanym JAAS)

klient: Jersey wywoływany poprzez JUnit (przez Maven)

mam JAAS skonfigurować na serwerze WWW. Używam części klienta jako testu.

Użytkownicy po stronie serwera są uwierzytelniani za pomocą formularza z podstawowym uwierzytelnianiem obsługiwanym przez JAAS. Oczywiście użytkownicy muszą zostać uwierzytelnieni, zanim będą mogli przeglądać określone strony.

Chciałbym móc zalogować się przez Jersey przed próbą uzyskania dostępu do zabezpieczonej strony. Jak to zrobić? Sprawdziłem, że możesz zdefiniować filtr, ale nie jestem do końca pewien, jak go użyć. A kiedy użytkownik jest zalogowany za pomocą formularza, jak mogę przejść (od strony klienta) do strony, którą naprawdę interesuję?

Byłbym bardzo wdzięczny, gdyby ktoś mógł mi pokazać przykład, jak to zrobić po stronie klienta z Jersey.

Mam następujący test JUnit przypadku metody:

@Test 
public void testLogin() 
     throws IOException 
{ 
    String URL_LOGIN = "http://localhost:9080/foo/auth.html"; 
    Client client = Client.create(); 

    String username = "me"; 
    String password = "me"; 

    final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password); 
    client.addFilter(authFilter); 
    client.addFilter(new LoggingFilter()); 

    WebResource webResource = client.resource(URL_LOGIN); 
    // I even tried: 
    // webResource.header("Authorization", "Basic " + "base64encoded_userid:password").type("application/xml"); 

    String page = webResource.post(String.class); 

    System.out.println(page); 
} 

Proszę uwaga:

1) http://localhost:9080/foo/auth.html jest strona ja ma być wyświetlany po pomyślnym auth.

2) Rzeczywiście widzę wyjście http://localhost:9080/foo/login.html.

3) Oczywiście, za pomocą przeglądarki, mogę z powodzeniem zalogować się za pomocą strony login.html.

Czego tu brakuje?

Odpowiedz

22

z podstawowymi auth nie trzeba iść do dowolnej strony logowania w ogóle. Jeśli serwer jest skonfigurowany do korzystania z podstawowego uwierzytelniania, możesz wysyłać żądania do dowolnej chronionej strony, jeśli w żądaniach podasz podstawowy nagłówek autoryzacji. Filtr Jersey zajmuje się tym. Tak więc, jeśli Basic auth naprawdę byłby tym, czego używa serwer, twój kod powinien zadziałać.

Biorąc pod uwagę, że nie działa i nie działa, jestem pewien, że serwer jest skonfigurowany do używania uwierzytelniania opartego na formularzach zamiast podstawowego uwierzytelniania.

Aby uwierzytelnianie formularzy działało, należy wysłać żądanie wpisu z danymi formularza, w tym nazwą użytkownika i hasłem, aby się zalogować, a następnie ustawić pliki cookie otrzymywane z serwera na kolejne żądania (ponieważ serwer - po zalogowaniu - ustawi plik cookie sesji).

Zobacz, jak wygląda plik login.html - powinien zawierać formularz. Jeśli używa standardowego formularza formularza serwletu, adres URL akcji tego formularza powinien być "j_security_check" i powinny istnieć dwa parametry formularza: j_username i j_password. Jeśli tak jest, można spróbować coś jak następuje:

String URL_LOGIN = "http://localhost:9080/foo/j_security_check"; 
String URL_DATA = "http://localhost:9080/foo/auth.html"; 
Client client = Client.create(); 

// add a filter to set cookies received from the server and to check if login has been triggered 
client.addFilter(new ClientFilter() { 
    private ArrayList<Object> cookies; 

    @Override 
    public ClientResponse handle(ClientRequest request) throws ClientHandlerException { 
     if (cookies != null) { 
      request.getHeaders().put("Cookie", cookies); 
     } 
     ClientResponse response = getNext().handle(request); 
     // copy cookies 
     if (response.getCookies() != null) { 
      if (cookies == null) { 
       cookies = new ArrayList<Object>(); 
      } 
      // A simple addAll just for illustration (should probably check for duplicates and expired cookies) 
      cookies.addAll(response.getCookies()); 
     } 
     return response; 
    } 
}); 

String username = "me"; 
String password = "me"; 

// Login: 
WebResource webResource = client.resource(URL_LOGIN); 

com.sun.jersey.api.representation.Form form = new Form(); 
form.putSingle("j_username", username); 
form.putSingle("j_password", password); 
webResource.type("application/x-www-form-urlencoded").post(form); 

// Get the protected web page: 
webResource = client.resource(URL_DATA); 
String response = webResource.get(String.class); 

Nie testowałem tego, więc może będzie kilka literówek i błędów.

+0

Martin, dzięki za ten przykład! Wydaje mi się, że to jest to, o co prosiłem. Jednak w wyniku 'odpowiedzi' uzyskuję stronę logowania ('/foo/login.html'), zamiast strony '/ foo/auth.html', która powinna wydrukować, że jestem zalogowany. Brak tu? Próbowałem twój przykład dokładnie taki, jaki jest, z wyjątkiem poprawienia com.sun.jersey.representation.Form do com.sun.jersey.representation.api.Form. – carlspring

+0

Użyj filtru logowania i sprawdź, jak wyglądają żądania i odpowiedzi - w szczególności odpowiedź na wpis. Sprawdź, czy serwer wysyła Set-Cookie w odpowiedzi i czy kolejne żądania klienta zawierają plik cookie. Również odpowiedź otrzymasz z postu - jeśli logowanie powiodło się, czy nie. Nie wiesz, czy w przypadku logowania formularza musisz najpierw spróbować zażądać chronionej strony, a dopiero potem zaloguj się - spróbuj. Zobacz także, jak wygląda strona login.html - jeśli naprawdę używa ona parametrów j_security_check i j_username oraz j_password. –

+0

Martin, używa j_security_check i j_username/j_password. Mam włączone logowanie twojego przykładu, aby zobaczyć nagłówki. Mam następujące wyniki, które opublikowałem na temat pastebin: http://pastebin.com/dGMHpk7g Być może mógłbyś również rzucić okiem ...? – carlspring

10

Nie używam Jersey, ale nie jest to kwestia Jersey jako taka.

Po pierwsze, musisz używać albo loginu FORM, albo uwierzytelniania BASIC; chyba że jest to rozwój niestandardowy, wątpię, że używasz "Formularza z podstawowym uwierzytelnieniem".

Jeśli korzystasz z uwierzytelniania podstawowego, rzeczy są dość proste (choć nieefektywne): uwierzytelnianie BASIC jest bezstanowe i musisz wysyłać nagłówek HTTP Authorization: Basic xxxx na KAŻDE żądanie.

Jeśli korzystasz z logowania FORM, sprawy nieco bardziej się angażują. Na każde żądanie należy przesłać identyfikator sesji (przechowywany w pliku cookie lub przy użyciu przepisywania adresów URL). Jeśli go nie wyślesz lub jeśli powiązana sesja zostanie unieważniona (ponieważ wygasła na przykład), serwer wyśle ​​302 (przekierowanie) i formularz logowania. Następnie należy wykonać FORM POST na adres URL wskazany w formularzu z nazwą użytkownika i hasłem jako parametrami. Jeśli uwierzytelnianie zakończy się pomyślnie, serwer wyśle ​​odpowiedź na pierwotne żądanie (i nowy identyfikator sesji). W tym scenariuszu programistyczny prośba musi zatem być w stanie

  • 1. Uchwyt ciasteczek (chyba że zmusi Przepisywanie URL co jest mało prawdopodobne)
  • 2.Wykrywanie kiedy dostają 302 i formularza logowania powrotem na zamówienie i zakończyć wymagane Formularz postu, zanim będą kontynuowane.
Dotyczy to każdego połączenia HTTP (AJAX, REST, itp.) I należy pamiętać, że fakt, że serwer korzysta z JAAS lub innego mechanizmu uwierzytelniania i autoryzacji, nie ma znaczenia: jest to problem zarządzania sesją.

Alternatywnie, Jersey specyficzne rozwiązanie jest dostępne przez przechwytywanie połączeń, tutaj:

How to get jersey logs at server?

+0

Dziękujemy! To jest trochę przydatna informacja. Bardzo doceniam, ale staram się wymyślić, jak prawidłowo to zrobić z klientem z Jersey. – carlspring

1

Dla mnie te zmiany rozwiązał problem:

String URL_LOGIN = "http://localhost:9080/foo/j_security_check"; 
String URL_DATA = "http://localhost:9080/foo/auth.html"; 
Client client = Client.create(); 

// add a filter to set cookies received from the server and to check if login has been triggered 
client.addFilter(new ClientFilter() { 
    private ArrayList<Object> cookies; 

    @Override 
    public ClientResponse handle(ClientRequest request) throws ClientHandlerException { 
     if (cookies != null) { 
      request.getHeaders().put("Cookie", cookies); 
     } 
     ClientResponse response = getNext().handle(request); 
     // copy cookies 
     if (response.getCookies() != null) { 
      if (cookies == null) { 
       cookies = new ArrayList<Object>(); 
      } 
      // A simple addAll just for illustration (should probably check for duplicates and expired cookies) 
      cookies.addAll(response.getCookies()); 
     } 
     return response; 
    } 
}); 

String username = "me"; 
String password = "me"; 


// Get the protected web page: (this will make the server know that someone will try to access the protected resource) 
WebResource webResource = client.resource(URL_DATA); 
String response = webResource.get(String.class); 


// Login: 
webResource = client.resource(URL_LOGIN); 

com.sun.jersey.api.representation.Form form = new Form(); 
form.putSingle("j_username", username); 
form.putSingle("j_password", password); 
webResource.type("application/x-www-form-urlencoded").post(form); 


// Get the protected web page: (this time the service will return the data) 
webResource = client.resource(URL_DATA); 
response = webResource.get(String.class); 
3

autoryzację na JAAS:

String URL_DATA = "http://localhost:9080/foo/auth.html"; 
    Client client = Client.create(); 

    String username = "me"; 
    String password = "me"; 

    client.addFilter(new HTTPBasicAuthFilter(username, password)); 

    // Get the protected web page: 
    WebResource webResource = client.resource(URL_DATA); 
    String response = webResource.get(String.class); 
    System.out.println(response); 
Powiązane problemy