带有请求标头的Tomcat身份验证

时间:2015-12-09 18:00:34

标签: tomcat servlets login passwords jdbcrealm

我在Tomcat 7上运行了一个Web应用程序。目前用户通过JDBCRealm登录密码。

在我的组织中,有一个身份验证服务器。用户将HTTP请求发送到该服务器,服务器以某种方式对它们进行身份验证,然后使用自定义HTTP标头将请求转发到我的应用程序,该标头指定经过身份验证的用户名(无密码)。

我希望使用此机制来验证用户的应用程序,同时保持JDBC领域。当用户向/login发送请求时,他们的请求将使用标头进行身份验证,并且他们将被重定向到主页,就好像他们使用标准j_security_check表单登录一样,但没有必须提供密码。

这是我到目前为止所提出的:

@WebFilter("/login/*")
public class LoginFilter implements Filter {

  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) req;
    HttpServletResponse httpResponse = (HttpServletResponse) res;

    String username = ... // Extract username from httpRequest, not an issue

    httpRequest.login(username, "???"); // Need to provide a password!

    httpResponse.sendRedirect(httpRequest.getContextPath() + "/pages/home.xhtml");

  }

}

当我为JDBCRealm提供正确的密码时,这是有效的,但过滤器中的密码不可用。

更新:我最后用自定义阀门解决了这个问题:

public class LoginValve extends ValveBase {

    @Override
    public void invoke(Request req, Response res) throws IOException, ServletException {

    if (!req.getRequestURI().equals(req.getContextPath() + "/login")) {
        getNext().invoke(req, res);
        return;
    }

    Session session = req.getSessionInternal();

    if (session.getPrincipal() == null) {
        String username = ... // From req
        List<String> roles = ... // From req
        session.setPrincipal(new GenericPrincipal(username, null, roles));
    }

    req.setUserPrincipal(session.getPrincipal());

    getNext().invoke(req, res);

}

我从稍后调用的过滤器进行重定向。

1 个答案:

答案 0 :(得分:1)

我有三个声誉点不能评论,所以我必须根据给定的信息回答,用猜测填补一些空白。

您可以实现&#34;身份验证&#34;通过继承javax.servlet.http.HttpServletRequestWrapper

重写getRemoteUser()和getUserPrincipal(),以便它们返回经过身份验证的用户的用户名,以及一个基本上可以创建任何内容的Principal对象。 JMXPrincipal应该方便使用。您可能还应该重写getAuthType()以返回HttpServletRequest.FORM_AUTH以使所有内容都很好地进行网格化。并根据Javadoc实现一个快速的logout()方法,该方法表示&#34;在请求时调用getUserPrincipal,getRemoteUser和getAuthType时,将null作为返回的值。&#34;

然后,在您的过滤器中,将传入的HttpServletRequest包装在您的包装器对象中,并将包装器对象传递给chain.doFilter()。

如果你想得到想象,你也可以在包装器上覆盖login()方法,它接受任何(或空)密码并创建将由getRemoteUser(),getUserPrincipal()返回的内部实例变量和getAuthType()。