我在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);
}
我从稍后调用的过滤器进行重定向。
答案 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()。