FAQ

[Tomcat-users] Connection.close() has already been called during login

Removeps-code
Jan 23, 2012 at 3:50 am
Am running Tomcat 7 and see this in the logs:

SEVERE: Exception performing authentication
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
at com.mysql.jdbc.Util.getInstance(Util.java:381)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018)
at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1512)
at org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:579)
at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:408)
at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
at pacific.tomcat.RootJDBCRealm.authenticate(SourceFile:71)
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:1773)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)


could the reason be ROOT/META-INF/context.xml which says

<Context>

<Realm className="pacific.tomcat.RootJDBCRealm"
driverName="pacific.driver.PacificMysqlDriver"
connectionName="auth" connectionPassword="..."
connectionURL="pacific@jdbc:mysql://localhost:3306"
userTable="user" userNameCol="username" userCredCol="password"
userRoleTable="user_role" roleNameCol="rolename"
digest="SHA1"/>

That is, should I be using a datasource realm instead?

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
reply

Search Discussions

10 responses

  • Mark Thomas at Jan 23, 2012 at 8:49 am

    On 23/01/2012 03:49, removeps-code@yahoo.com wrote:
    Am running Tomcat 7 and see this in the logs:

    SEVERE: Exception performing authentication
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.Util.getInstance(Util.java:381)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018)
    at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1512)
    at org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:579)
    at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:408)
    at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
    at pacific.tomcat.RootJDBCRealm.authenticate(SourceFile:71)
    The above line is key. You are not using Tomcat's JDBCRealm.
    at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:1773)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)


    could the reason be ROOT/META-INF/context.xml which says

    <Context>

    <Realm className="pacific.tomcat.RootJDBCRealm"
    driverName="pacific.driver.PacificMysqlDriver"
    connectionName="auth" connectionPassword="..."
    connectionURL="pacific@jdbc:mysql://localhost:3306"
    userTable="user" userNameCol="username" userCredCol="password"
    userRoleTable="user_role" roleNameCol="rolename"
    digest="SHA1"/>

    That is, should I be using a datasource realm instead?
    Yes.

    Mark

    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Removeps-code at Jan 23, 2012 at 6:22 pm
    Initially I thought that my RootJDBCRealm might be the problem, but how can that be? RootJDBCRealm extends Tomcat's own JDBCRealm. It overrides authenticate to call super.authenticate and if there are 3 failures (in that super.authenticate returns null), then it locks out the user. So could the user of RootJDBCRealm still be a problem? Thanks.

    --- On Mon, 1/23/12, Mark Thomas wrote:
    From: Mark Thomas <markt@apache.org>
    Subject: Re: Connection.close() has already been called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 12:49 AM
    On 23/01/2012 03:49, removeps-code@yahoo.com
    wrote:
    Am running Tomcat 7 and see this in the logs:

    SEVERE: Exception performing authentication
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:
    Connection.close() has already been called. Invalid
    operation in this state.
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
    Method)
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at
    java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at
    com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at
    com.mysql.jdbc.Util.getInstance(Util.java:381)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at
    com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018)
    at
    com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1512)
    at
    org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:579)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:408)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
    at
    pacific.tomcat.RootJDBCRealm.authenticate(SourceFile:71)

    The above line is key. You are not using Tomcat's
    JDBCRealm.
    at
    org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
    at
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
    at
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at
    org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:1773)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at
    java.lang.Thread.run(Thread.java:662)

    could the reason be ROOT/META-INF/context.xml which says
    <Context>

    <Realm
    className="pacific.tomcat.RootJDBCRealm"

    driverName="pacific.driver.PacificMysqlDriver"

    connectionName="auth" connectionPassword="..."

    connectionURL="pacific@jdbc:mysql://localhost:3306"
    userTable="user"
    userNameCol="username" userCredCol="password"

    userRoleTable="user_role" roleNameCol="rolename"
    digest="SHA1"/>

    That is, should I be using a datasource realm
    instead?

    Yes.

    Mark

    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Chema at Jan 23, 2012 at 6:29 pm

    2012/1/23 <removeps-code@yahoo.com>:
    Initially I thought that my RootJDBCRealm might be the problem, but how can that be?  RootJDBCRealm extends Tomcat's own JDBCRealm.  It >overrides authenticate to call super.authenticate and if there are 3 failures (in that super.authenticate returns null), then it locks out the user.  So could >the user of RootJDBCRealm still be a problem?  Thanks.
    From Tomcat 7 docs:
    "The JDBCRealm is not recommended for production use as it is single
    threaded for all authentication and authorization options. Use the
    DataSourceRealm instead.
    The UserDatabaseRealm is not intended for large-scale installations.
    It is intended for small-scale, relatively static environments."

    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Daniel Mikusa at Jan 23, 2012 at 6:56 pm

    On Mon, 2012-01-23 at 10:21 -0800, removeps-code@yahoo.com wrote:
    Initially I thought that my RootJDBCRealm might be the problem, but how can that be?
    RootJDBCRealm extends Tomcat's own JDBCRealm. It overrides authenticate to call super.authenticate and if there are 3 failures (in that super.authenticate returns null), then it locks out the user.
    Sounds a lot like the LockOutRealm.

    https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#LockOutRealm

    Any reason you opted not to use it?

    Dan
    So could the user of RootJDBCRealm still be a problem? Thanks.

    --- On Mon, 1/23/12, Mark Thomas wrote:
    From: Mark Thomas <markt@apache.org>
    Subject: Re: Connection.close() has already been called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 12:49 AM
    On 23/01/2012 03:49, removeps-code@yahoo.com
    wrote:
    Am running Tomcat 7 and see this in the logs:

    SEVERE: Exception performing authentication
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:
    Connection.close() has already been called. Invalid
    operation in this state.
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
    Method)
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at
    java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at
    com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at
    com.mysql.jdbc.Util.getInstance(Util.java:381)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at
    com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018)
    at
    com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1512)
    at
    org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:579)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:408)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
    at
    pacific.tomcat.RootJDBCRealm.authenticate(SourceFile:71)

    The above line is key. You are not using Tomcat's
    JDBCRealm.
    at
    org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
    at
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
    at
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at
    org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:1773)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at
    java.lang.Thread.run(Thread.java:662)

    could the reason be ROOT/META-INF/context.xml which says
    <Context>

    <Realm
    className="pacific.tomcat.RootJDBCRealm"

    driverName="pacific.driver.PacificMysqlDriver"

    connectionName="auth" connectionPassword="..."

    connectionURL="pacific@jdbc:mysql://localhost:3306"
    userTable="user"
    userNameCol="username" userCredCol="password"

    userRoleTable="user_role" roleNameCol="rolename"
    digest="SHA1"/>

    That is, should I be using a datasource realm
    instead?

    Yes.

    Mark

    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Removeps-code at Jan 23, 2012 at 7:55 pm

    --- On Mon, 1/23/12, Daniel Mikusa wrote:

    From: Daniel Mikusa <dmikusa@vmware.com>
    Subject: Re: Connection.close() has already been called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 10:55 AM
    On Mon, 2012-01-23 at 10:21 -0800, removeps-code@yahoo.com
    wrote:
    Initially I thought that my RootJDBCRealm might be the
    problem, but how can that be?
    RootJDBCRealm extends Tomcat's own JDBCRealm.  It
    overrides authenticate to call super.authenticate and if
    there are 3 failures (in that super.authenticate returns
    null), then it locks out the user.

    Sounds a lot like the LockOutRealm.

    https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#LockOutRealm
    Any reason you opted not to use it?

    Sorry, I did not know about this class. Will this class work if you have many Tomcats on different machines (possibly load balancing) so regardless of which exact machine the user is directed to, lock realm will know the number of failed login attempts on other machines?


    Dan
    So could the user of RootJDBCRealm
    still be a problem?  Thanks.
    --- On Mon, 1/23/12, Mark Thomas wrote:
    From: Mark Thomas <markt@apache.org>
    Subject: Re: Connection.close() has already been
    called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 12:49 AM
    On 23/01/2012 03:49, removeps-code@yahoo.com
    wrote:
    Am running Tomcat 7 and see this in the
    logs:
    SEVERE: Exception performing authentication
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:
    Connection.close() has already been called.
    Invalid
    operation in this state.
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
    Method)
    at
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at
    java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at
    com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at
    com.mysql.jdbc.Util.getInstance(Util.java:381)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
    at
    com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018)
    at
    com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1512)
    at
    org.apache.catalina.realm.JDBCRealm.getPassword(JDBCRealm.java:579)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:408)
    at
    org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
    at
    pacific.tomcat.RootJDBCRealm.authenticate(SourceFile:71)
    The above line is key. You are not using
    Tomcat's
    JDBCRealm.
    at
    org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:295)
    at
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:450)
    at
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at
    org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:1773)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at
    java.lang.Thread.run(Thread.java:662)

    could the reason be
    ROOT/META-INF/context.xml which
    says
    <Context>

    <Realm
    className="pacific.tomcat.RootJDBCRealm"

    driverName="pacific.driver.PacificMysqlDriver"

    connectionName="auth" connectionPassword="..."
    connectionURL="pacific@jdbc:mysql://localhost:3306"
    userTable="user"
    userNameCol="username" userCredCol="password"
    userRoleTable="user_role" roleNameCol="rolename"
    digest="SHA1"/>
    That is, should I be using a datasource
    realm
    instead?

    Yes.

    Mark
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Christopher Schultz at Jan 23, 2012 at 8:16 pm
    To whom it may concern,
    On 1/23/12 2:54 PM, removeps-code@yahoo.com wrote:
    Sorry, I did not know about [LockOutRealm]. Will this class work
    if you have many Tomcats on different machines (possibly load
    balancing) so regardless of which exact machine the user is
    directed to, lock realm will know the number of failed login
    attempts on other machines?
    No, neither this nor any other Tomcat realms are cluster-aware.

    If you want to track authentication failures across a cluster, you
    could subclass LockOutRealm and override these methods:

    - - isLocked
    - - unlock
    - - registerAuthFailure

    This will allow you to handle the cluster-sync behavior separately
    from the authentication behavior which this class already handles.

    I'm interested in seeing what you come up with for communicating with
    the rest of the cluster.

    - -chris


    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Removeps-code at Jan 23, 2012 at 9:21 pm
    My code does not talk to another cluster as I have a single Tomcat only, but just wondering how one would scale.

    Maybe the strategy to handle clusters is to write information, such as the list of the users to the number of times they have logged in in the last hour, into a location shared by all machines. In my code below the code is stored in failedAttempts which is a Map<String /*username/*, FailedAttempt> where FailedAttempt represents the number of times the user has logged in in the last hour or whatever. It is in-memory, which is fine for one Tomcat.

    But we could move this Map into a file that is on a mounted drive available from all Tomcat machines, or we could store it in the database. Either way we have to synchronize writes to the file or database, and I think database does this automatically, and maybe FileLock will do the job for the files. But anyway, it sounds complicated.

    As for my my authenticate it was as follows, although I don't see this should cause the failure in the subject of this email -- "Connection.close() has already been called during login":

    public Principal authenticate(String username, String credentials)
    {
    threadUserLockedOut.remove();
    long curTime = System.currentTimeMillis();
    FailedAttempt failedAttempt = failedAttempts.get(username);
    if (failedAttempt != null && failedAttempt.checkFailedAttemptsReached(curTime))
    {
    threadUserLockedOut.set(Boolean.TRUE);
    return null;
    }
    Principal result = super.authenticate(username, credentials);
    if (result == null)
    {
    if (failedAttempt != null)
    {
    failedAttempt.incNumFailedAttempts();
    if (failedAttempt.maxFailedAttemptsReached())
    {
    failedAttempt.setFirstFailedTime(curTime);
    logger.warn("User '" + username + "' is locked out after " + MAX_FAILED_ATTEMPTS + " failed attempts");
    threadUserLockedOut.set(Boolean.TRUE);
    return null;
    }
    }
    else
    {
    failedAttempt = new FailedAttempt(curTime);
    failedAttempts.put(username, failedAttempt);
    }
    }
    else
    {
    if (failedAttempt != null)
    {
    failedAttempts.remove(username);
    }
    }
    return result;
    }


    --- On Mon, 1/23/12, Christopher Schultz wrote:
    From: Christopher Schultz <chris@christopherschultz.net>
    Subject: Re: Connection.close() has already been called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 12:15 PM
    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    To whom it may concern,

    On 1/23/12 2:54 PM, removeps-code@yahoo.com
    wrote:
    Sorry, I did not know about [LockOutRealm].  Will
    this class work
    if you have many Tomcats on different machines
    (possibly load
    balancing) so regardless of which exact machine the user is
    directed to, lock realm will know the number of failed login
    attempts on other machines?
    No, neither this nor any other Tomcat realms are
    cluster-aware.

    If you want to track authentication failures across a
    cluster, you
    could subclass LockOutRealm and override these methods:

    - - isLocked
    - - unlock
    - - registerAuthFailure

    This will allow you to handle the cluster-sync behavior
    separately
    from the authentication behavior which this class already
    handles.

    I'm interested in seeing what you come up with for
    communicating with
    the rest of the cluster.

    - -chris


    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Christopher Schultz at Jan 23, 2012 at 10:43 pm
    To whom it may concern,
    On 1/23/12 4:20 PM, removeps-code@yahoo.com wrote:
    My code does not talk to another cluster as I have a single Tomcat
    only, but just wondering how one would scale. Me too.
    Maybe the strategy to handle clusters is to write information, such
    as the list of the users to the number of times they have logged
    in in the last hour, into a location shared by all machines.
    That sounds fairly straightforward.
    In my code below the code is stored in failedAttempts which is a
    Map<String /*username/*, FailedAttempt> where FailedAttempt
    represents the number of times the user has logged in in the last
    hour or whatever. It is in-memory, which is fine for one Tomcat.
    Right. This is how Tomcat does things in its own LockOutRealm. Take a
    look at the code. It works with all realm types (see the code for the
    different authenticate() methods it implements).
    But we could move this Map into a file that is on a mounted drive
    available from all Tomcat machines, or we could store it in the
    database. Either way we have to synchronize writes to the file or
    database, and I think database does this automatically, and maybe
    FileLock will do the job for the files. But anyway, it sounds
    complicated.
    memcached. Cassandra. Whatever.
    As for my my authenticate it was as follows, although I don't see
    this should cause the failure in the subject of this email --
    "Connection.close() has already been called during login":
    Yup, it certainly doesn't look like your code does anything with the
    superclass's Connection.
    public Principal authenticate(String username, String credentials)
    { threadUserLockedOut.remove();
    Why in the world are you using a ThreadLocal in here?

    It makes me wonder what other odd things you are doing in your Realm
    (or anywhere else for that matter).

    - -chris


    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Removeps-code at Jan 23, 2012 at 11:54 pm

    --- On Mon, 1/23/12, Christopher Schultz wrote:

    From: Christopher Schultz <chris@christopherschultz.net>
    Subject: Re: Connection.close() has already been called during login
    To: "Tomcat Users List" <users@tomcat.apache.org>
    Date: Monday, January 23, 2012, 2:42 PM
    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    To whom it may concern,

    On 1/23/12 4:20 PM, removeps-code@yahoo.com
    wrote:
    My code does not talk to another cluster as I have a
    single Tomcat
    only, but just wondering how one would scale. Me too.
    Maybe the strategy to handle clusters is to write
    information, such
    as the list of the users to the number of times
    they have logged
    in in the last hour, into a location shared by all
    machines.

    That sounds fairly straightforward.
    In my code below the code is stored in failedAttempts
    which is a
    Map<String /*username/*, FailedAttempt> where
    FailedAttempt
    represents the number of times the user has logged in
    in the last
    hour or whatever. It is in-memory, which is fine for
    one Tomcat.

    Right. This is how Tomcat does things in its own
    LockOutRealm. Take a
    look at the code. It works with all realm types (see the
    code for the
    different authenticate() methods it implements).
    But we could move this Map into a file that is on a
    mounted drive
    available from all Tomcat machines, or we could store it in the
    database. Either way we have to synchronize writes to
    the file or
    database, and I think database does this
    automatically, and maybe
    FileLock will do the job for the files. But anyway, it sounds
    complicated.
    memcached. Cassandra. Whatever.
    As for my my authenticate it was as follows, although
    I don't see
    this should cause the failure in the subject of this email --
    "Connection.close() has already been called during
    login":

    Yup, it certainly doesn't look like your code does anything
    with the
    superclass's Connection.
    public Principal authenticate(String username, String
    credentials)
    { threadUserLockedOut.remove();
    Why in the world are you using a ThreadLocal in here?
    The use of the ThreadLocal is unrelated to the connection timing out. It's just a variable to indicate that in this thread the user is locked out. It is used later by my RootFormAuthenticator which extends FormAuthenticator to print out a message like "Your account has been locked out due to N failed attempts". FYI

    @Override
    protected void forwardToErrorPage(Request request, HttpServletResponse response, LoginConfig loginConfig) throws IOException
    {
    ...
    if (realm.isThreadUserLockedOut())
    {
    message.append("Your account has been locked out due
    ...
    }
    else
    {
    message.append("Sorry, the username or password you supplied is invalid. Please try again.");
    }
    realm.clearThreadUserLockedOut();
    request.setAttribute("loginErrorMessage", message);
    super.forwardToErrorPage(request, response, loginConfig);
    }


    The actual error page, which is a jsp page, has on it the following HTML

    <c:out value="${requestScope.loginErrorMessage}"/>


    It makes me wonder what other odd things you are doing in
    your Realm
    (or anywhere else for that matter).

    - -chris


    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org
  • Christopher Schultz at Jan 23, 2012 at 7:53 pm
    To whom it may concern,
    On 1/23/12 1:21 PM, removeps-code@yahoo.com wrote:
    Initially I thought that my RootJDBCRealm might be the problem,
    but how can that be? RootJDBCRealm extends Tomcat's own JDBCRealm.
    It overrides authenticate to call super.authenticate and if there
    are 3 failures (in that super.authenticate returns null), then it
    locks out the user. So could the user of RootJDBCRealm still be a
    problem?
    It obviously depends upon what code is in RootJCBDRealm. Care you share?

    As someone else already pointed out, you might want to look at
    LockOutRealm.

    - -chris


    ---------------------------------------------------------------------
    To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
    For additional commands, e-mail: users-help@tomcat.apache.org

Related Discussions

Discussion Navigation
viewthread | post