2013-03-25 2 views
6

Я хочу написать сервлет, который обертывает множество ресурсов и должен защищать их с помощью базового HTTP-аутентификации; отправленное имя пользователя/пароль будет проверяться перед бэкэнд-базой данных перед тем, как обслуживать файл.Реализация базовой аутентификации HTTP в сервлете

Есть ли у кого-нибудь рабочие примеры этого? Я попробовал образец на http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications, но он продолжал возвращать IllegalStateException в вызове sendError.

+0

Опубликуйте сервлет –

+0

Я просто использовал образец в ссылке. –

+1

@ Рой, пример в твоем посте отлично работал для меня. Я не уверен, почему он дал вам ошибку. не могли бы вы обновить свой пост с помощью stacktrace? –

ответ

17

Вот код, который возвращает объект Credential (объект bean-объекта, содержащий логин и пароль).

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

Он хорошо работает, даже с помощью пароля, как фанк, как: & =/é $ £.

Вот основной тестовый модуль для класса, используя 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

Небольшое примечание об использовании класса 'StringTokenizer', взятое из официальной документации Java:« StringTokenizer »- это унаследованный класс, который сохраняется по соображениям совместимости, хотя его использование не рекомендуется в новом коде. Рекомендуется, чтобы кто-либо, кто ищет эту функциональность используйте вместо этого метод 'split'' String' или пакет java.util.regex. " – xonya

+0

Откуда взялся класс Base64? –

+0

Я не кодировал Java через некоторое время, но не является частью Base64 J2SE? как в https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html –

Смежные вопросы