2013-03-25 8 views
6

Desidero scrivere un servlet che racchiuda un insieme di risorse e deve proteggerle con un'autenticazione HTTP di base; il nome utente/pass inviato verrà verificato sul database di back-end prima di servire il file.Implementazione dell'autenticazione di base HTTP in un servlet

Qualcuno ha qualche esempio funzionante di questo? Ho provato il campione a http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications ma continuava a restituire un IllegalStateException nella chiamata sendError.

+0

Inserisci servlet –

+0

ho appena usato il campione nel link. –

+1

@Roy, l'esempio nel tuo post ha funzionato bene per me. Non sono sicuro del motivo per cui ti ha dato un errore. potresti aggiornare il tuo post con lo stacktrace? –

risposta

17

Ecco un codice che restituisce un oggetto Credential (oggetto bean che contiene login e password).

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

Funziona bene, anche con una password come funky come:? & =/E $ £.

Ecco un test di base unità per la classe, utilizzando 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

Una piccola nota sull'uso della classe 'StringTokenizer' presa dalla documentazione ufficiale di Java:" 'StringTokenizer' è una classe legacy che viene mantenuta per ragioni di compatibilità anche se il suo uso è scoraggiato nel nuovo codice. Si raccomanda che chiunque cerchi questa funzionalità usa invece il metodo 'split' di' String' o il pacchetto java.util.regex. " – xonya

+0

Da dove proviene la classe Base64? –

+0

Non ho codificato con Java da un po 'di tempo, ma non è parte Base64 di J2SE? come in https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html –

Problemi correlati