2013-03-25 96 views
6

我想編寫一個環繞一組資源並需要使用基本HTTP認證來保護它們的servlet;在提供文件之前,提交的用戶名/密碼將在後端數據庫中進行檢查。在servlet中實現HTTP基本認證

有沒有人有這個工作的例子?我嘗試了http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications的示例,但它在sendError調用中不斷返回IllegalStateException

+0

發表你的servlet – 2013-03-25 09:54:47

+0

我只是用樣品中的鏈接。 – 2013-03-25 11:13:19

+1

@羅伊,你的文章中的例子對我來說工作得很好。我不知道爲什麼它給你錯誤。你能否用stacktrace更新你的帖子? – 2013-03-25 11:28:06

回答

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

它運作良好,即使有密碼時髦的:& =/E $£。

下面是這個類的基本單元測試,使用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

關於從官方的Java文檔中使用StringTokenizer類的一點注意:「'StringTokenizer'是一個遺留類,爲了兼容性的原因,儘管在新代碼中不鼓勵使用它,但建議任何尋求這種功能的人改爲使用'String'的'split'方法或java.util.regex包。「 – xonya 2015-10-28 08:35:25

+0

Base64類從哪裏來? – 2016-11-04 11:50:38

+0

我有一段時間沒有用Java編碼,但是不是J2SE的Base64部分?如https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html中所示 – 2016-11-09 17:03:34