【问题标题】:Exceptions happen when using JDBCRealm使用 JDBCRealm 时发生异常
【发布时间】:2017-11-23 20:02:02
【问题描述】:

如何调试由request.login()方法引起的javax.servlet.ServletException
登录.java

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    PrintWriter out = response.getWriter();
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    try {       
        request.login(username, password); // Exceptions happen.
        out.println("logged in");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

tomcat server.xml

  <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>


<!-- added by myself>
    <Context>
      <Realm className="org.apache.catalina.realm.JDBCRealm" 
          connectionName="root" 
          connectionPassword="password" 
          connectionURL="jdbc:mysql://localhost/forum?autoReconnectForPools=true&amp;characterEncoding=UTF-8" 
          digest="MD5" 
          driverName="com.mysql.jdbc.Driver" 
          roleNameCol="role_name" 
          userCredCol="user_pass"
          userNameCol="user_name"
          userRoleTable="user_roles"
          userTable="users" />
     </Context>

例外:

javax.servlet.ServletException: 登录失败 org.apache.catalina.authenticator.AuthenticatorBase.doLogin(AuthenticatorBase.java:963) 在 org.apache.catalina.authenticator.AuthenticatorBase.login(AuthenticatorBase.java:943) 在 org.apache.catalina.connector.Request.login(Request.java:2768) 在 org.apache.catalina.connector.RequestFacade.login(RequestFacade.java:1064) 在 com.example.Login.doPost(Login.java:55) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:650) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:731) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) 在 org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445) 在 org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115) 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637) 在 org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • 登录前创建会话。代码:if (request.getUserPrincipal() == null) { request.getSession(); // create session request.login(username, password); }
  • 您是如何在数据库中填充密码列user_pass 的?从外观上看应该是 MD5 散列
  • @Steve 我使用insert into users(user_name, user_pass) values ('1', MD5('1'));。只是为了测试。
  • @Jay Smith 你的意思是注释掉request.login(username, password);这一行吗?如果是这样,如何测试用户名和密码是否正确?request.getUserPrincipal()在我的程序中返回null。
  • 不要评论这一行。如果request.getUserPrincipal() 返回 null 则没有经过身份验证的用户,因此您可以创建会话并进行登录。您可以将经过身份验证的用户存储在创建的会话对象中

标签: java tomcat servlets jakarta-ee


【解决方案1】:

您将获得Login fail,因为您用于在数据库中创建散列密码的方法与 Tomcat JDBCRealm 使用的方法不同。

您应该使用Tomcat提供的digest工具(在您的Tomcat安装的bin目录中)生成哈希密码,而不是使用MySql MD5函数。

例如(密码为“1”):

[steve@Steves-MacBook-Pro apache-tomcat-8.0.18]$ bin/digest.sh -s 0 -a MD5 1
1:$1$c4ca4238a0b923820dcc509a6f75849b

我预计此结果 ($1$c4ca4238a0...) 与您将在数据库表中观察到的结果不同。

此外,根据Tomcat 8 Realm Configuration HOW-TO,您应该消化值{username}:{realm}:{cleartext-password} 而不仅仅是{cleartext-password},并将其存储在数据库中。 {realm} 值来自 web.xml 文件中的 &lt;realm-name&gt;

【讨论】:

  • 是的,不一样。每次我用密码'1'运行digest命令,值都不一样。那么如何存储密码呢?
  • 看来你需要指定一个salt长度为0
  • @Steve C 我使用的是 tomcat-7.0.78。根据文档,我使用RealmBase.Digest("1:Authentication required:1", "MD5", "UTF-8") 的值来测试密码为“1”的用户“1”并将其存储在数据库中。但同样的例外仍然存在。
猜你喜欢
  • 2011-07-27
  • 2020-07-13
  • 2012-12-20
  • 1970-01-01
  • 2015-12-06
  • 2015-02-21
  • 2014-12-22
  • 2012-05-27
  • 2017-04-05
相关资源
最近更新 更多