【问题标题】:Implementing HTTP Basic Authentication in a servlet在 servlet 中实现 HTTP 基本身份验证
【发布时间】:2013-03-14 17:57:18
【问题描述】:

我想编写一个 servlet 来包装一组资源并需要使用基本的 HTTP 身份验证来保护它们;在提供文件之前,将根据后端数据库检查提交的用户名/密码。

有人有这方面的工作示例吗?我在http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications 尝试了示例,但它在sendError 调用中不断返回IllegalStateException

【问题讨论】:

  • 我只是使用了链接中的示例。
  • @Roy,您帖子中的示例对我来说效果很好。我不确定为什么它给你错误。你能用堆栈跟踪更新你的帖子吗?
  • IMO,servlet 过滤器更适合于此,因为它独立于 servlet,并且可以在必要时应用于多个 servlet。这可能比您目前需要的更先进,因此请仅将其视为友好的指针,而不是批评。

标签: java servlets basic-authentication


【解决方案1】:

这里是一些返回 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();
}

【讨论】:

  • 关于 StringTokenizer 类的使用的一点说明,取自官方 Java 文档:“StringTokenizer 是一个遗留类,出于兼容性原因保留,尽管在新代码中不鼓励使用它。它建议任何寻求此功能的人使用 Stringsplit 方法或 java.util.regex 包。"
  • Base64 类从何而来?
  • 我已经有一段时间没有使用 Java 编码了,但是 Base64 不是 J2SE 的一部分吗?如docs.oracle.com/javase/8/docs/api/java/util/Base64.html
猜你喜欢
  • 2011-12-06
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 2011-11-12
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多