I have an annoying error which I can't solve for quite a while. I recently was introduced to container-based security and try to implement it. I have configure the realm as following:
<Realm className="org.apache.catalina.realm.JDBCRealm"
debug="99"
driverName="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://127.0.0.1:3306/identify"
connectionName="adm" connectionPassword="pw"
userTable="users" userNameCol="login"
userCredCol="password"
allRolesMode="authOnly" />
</Realm>
Unfortunately I can't login with this. The log error messages are:
SEVERE: Exception performing authentication
java.sql.SQLException: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version
for the right syntax to use near 'null WHERE login = 'user1'' at line 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2928)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1571)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1666)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2994)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:936)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1030)
at org.apache.catalina.realm.JDBCRealm.getRoles(JDBCRealm.java:640)
at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:430)
at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:355)
at org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:146)
at org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:180)
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:282)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:440)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:851)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:278)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
Please notice the '' around the user name... Is this correct?
As you see I also use allRolesMode="authOnly"
, because I don't need this functionality and moreover the database doesn't have and won't ever have an additional column for user roles (it is quite pointless if won't use it than every user will have the same value in this column - big waste of recourses.).
The server is Tomcat 7.0.19
You have to set the
userRoleTable
androleNameCol
properties in case ofallRolesMode="authOnly"
too. Without them the SQL query will contain the Stringnull
(as you can see in the message of the exception). The value ofuserRoleTable
could be the same as the value ofuserTable
, androleNameCol
also could be same asuserNameCol
.A simple workaround is creating an SQL view which emulates the
roles
table:And a solution:
(Surprisingly it works without any
allRolesMode
.)The required
web.xml
snippets:(Note: Lets say you have 1 million users, a new attribute in the
users
table with one millionuser\0
string would cost only around 5 megabytes. I agree with that this is not a beautiful solution but it's not intolerable big nowadays.)