在Servlet中实现HTTP基本身份验证

8

我刚刚使用了链接中的示例。 - Roy Tang
1
@Roy,你在帖子中的示例对我来说很好用。我不确定为什么它会给你错误。你能否更新你的帖子并提供堆栈跟踪信息? - Avinash K.P
在我看来,一个Servlet过滤器更加适合这种情况,因为它独立于Servlet并且可以应用于多个Servlet(如果需要的话)。这可能比你目前所需的更高级,请把它仅仅视为友好的指针,而不是批评。 - Taylor
1个回答

22

这里有一段代码,返回一个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是一个遗留类,为了兼容性而保留,尽管在新代码中不建议使用。建议寻求此功能的任何人改用Stringsplit方法或java.util.regex包。” - xonya
Base64类来自哪里? - Mateus Viccari
我已经有一段时间没用Java编程了,但Base64不是J2SE的一部分吗?就像https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html中所示。 - Dirty Henry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接