0
votes

How can I debug javax.servlet.ServletException caused by request.login() method?
Login.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>

Exception:

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

1
Create Session before logging in. Code: if (request.getUserPrincipal() == null) { request.getSession(); // create session request.login(username, password); }Jay Smith
How did you populate the password column user_pass in the database? It should be MD5 hashed by the look of itSteve C
@Steve I use insert into users(user_name, user_pass) values ('1', MD5('1'));. Just for test.user7328234
@Jay Smith Do you mean comment out the line request.login(username, password);? If so, how to test the username and password is correct?request.getUserPrincipal() returns null in my program.user7328234
Don't comment this line. If request.getUserPrincipal() returns null there is no authenticated user thus you can create session and do login. You can store authenticated user in created session objectJay Smith

1 Answers

1
votes

You are getting a Login fail because the method that you used to create the hashed password in the database is different from that used by the Tomcat JDBCRealm.

Instead of using the MySql MD5 function, you should use the digest tool provided by Tomcat (in the bin directory of your Tomcat installation) to generate the hashed password.

For example (with a password of "1"):

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

I expect that this result ($1$c4ca4238a0...) is different from what you will observe in the database table.

Additionally, according to Tomcat 8 Realm Configuration HOW-TO, you should digest the values {username}:{realm}:{cleartext-password} instead of just {cleartext-password} and store that in the database. The {realm} value comes from the <realm-name> in your web.xml file.