【发布时间】:2016-03-15 03:21:20
【问题描述】:
我有一个在 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);
}
我从稍后调用的过滤器进行重定向。
【问题讨论】:
-
只从与领域使用的相同用户数据库中获取它?
-
密码是在数据库中散列的,而且我不需要密码,我只是想将用户设置为已登录,这似乎很浪费资源。
-
然后将领域配置为不再对其进行哈希处理。
-
我无法以明文形式保存密码
-
那么用户注册是通过同一个领域发生的吗?这是非常出乎意料的,因为您显然有一个单独的身份验证服务器。好吧,只需添加另一个不会散列密码并将用作只读领域的领域,这样您就可以使用已经散列的密码登录。
标签: tomcat servlets login passwords jdbcrealm