2013-03-25 21 views
6

Chcę napisać serwlet, który owija się wokół zestawu zasobów i musi je chronić za pomocą podstawowego uwierzytelniania HTTP; przedłożona nazwa użytkownika/hasło zostaną sprawdzone przed bazą danych przed udostępnieniem pliku.Implementowanie podstawowego uwierzytelniania HTTP w serwlecie

Czy ktoś ma jakieś działające przykłady tego? Próbowałem próbkę pod numerem http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications, ale nadal zwracałem numer IllegalStateException w rozmowie .

+0

Wyślij swój serwlet –

+0

tylko używane próbkę w linku. –

+1

@Roy, przykład w twoim poście działał dobrze dla mnie. Nie jestem pewien, dlaczego podał ci błąd. czy mógłbyś zaktualizować swój post za pomocą stacktrace? –

Odpowiedz

17

Oto kod, który zwraca obiekt Credential (obiekt bean zawierający login i hasło).

public Credentials credentialsWithBasicAuthentication(HttpServletRequest req) { 
    String authHeader = req.getHeader("Authorization"); 
    if (authHeader != null) { 
     StringTokenizer st = new StringTokenizer(authHeader); 
     if (st.hasMoreTokens()) { 
      String basic = st.nextToken(); 

      if (basic.equalsIgnoreCase("Basic")) { 
       try { 
        String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); 
        LOG.debug("Credentials: " + credentials); 
        int p = credentials.indexOf(":"); 
        if (p != -1) { 
         String login = credentials.substring(0, p).trim(); 
         String password = credentials.substring(p + 1).trim(); 

         return new Credentials(login, password); 
        } else { 
         LOG.error("Invalid authentication token"); 
        } 
       } catch (UnsupportedEncodingException e) { 
        LOG.warn("Couldn't retrieve authentication", e); 
       } 
      } 
     } 
    } 

    return null; 
} 

To działa dobrze, nawet z hasłem jako ostry jak: & =/E $ £.

Oto podstawowe testy jednostkowe dla klasy, stosując JMock:

public void testCredentialsWithBasicAuthentication() { 
    // Setup 
    final HttpServletRequest request = context.mock(HttpServletRequest.class); 

    AuthentificationHelper helper = new AuthentificationHelper(); 
    String login = "mickael"; 
    String password = ":&=/?é$£"; 
    String base64Hash = Base64.encodeString(login + ":" + password); 
    final String authHeader = "Basic " + base64Hash; 

    // Expectations 
    context.checking(new Expectations() { 
     { 
      oneOf (request).getHeader("Authorization"); 
      will(returnValue(authHeader)); 
     } 
    }); 

    // Execute 
    Credentials credentials = helper.credentialsWithBasicAuthentication(request); 

    // Verify 
    assertNotNull(credentials); 
    assertEquals(login, credentials.getLogin()); 
    assertEquals(password, credentials.getPassword()); 

    context.assertIsSatisfied(); 
} 
+1

Mała uwaga dotycząca użycia klasy 'StringTokenizer' wziętej z oficjalnej dokumentacji Java:' 'StringTokenizer' jest klasą starszą, która jest zachowywana ze względu na kompatybilność, chociaż jej użycie jest odradzane w nowym kodzie. Zaleca się, aby każdy, kto szukał tej funkcji zamiast tego użyj metody 'split' z' String' lub pakietu java.util.regex. " – xonya

+0

Skąd pochodzi klasa Base64? –

+0

Nie kodowałem z Javą od jakiegoś czasu, ale nie jest częścią J2SE Base64? jak w https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html –

Powiązane problemy