开发者

Authentication without authorization on Tomcat 7

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.cata开发者_C百科lina.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 and roleNameCol properties in case of allRolesMode="authOnly" too. Without them the SQL query will contain the String null (as you can see in the message of the exception). The value of userRoleTable could be the same as the value of userTable, and roleNameCol also could be same as userNameCol.

A simple workaround is creating an SQL view which emulates the roles table:

CREATE VIEW roles (username, role)
AS SELECT username, 'user' FROM users;

And a solution:

<Realm className="org.apache.catalina.realm.JDBCRealm" 
    driverName="com.mysql.jdbc.Driver" 
    connectionURL="jdbc:mysql://127.0.0.1:3306/test" 
    connectionName="..." connectionPassword="..." 
    userTable="users" userNameCol="username" userCredCol="password" 
    userRoleTable="users" roleNameCol="username"
/> 

(Surprisingly it works without any allRolesMode.)

The required web.xml snippets:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>protected zone</web-resource-name>
        <url-pattern>/prot/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>
</security-constraint>

<security-role>
     <role-name>*</role-name>
</security-role>

(Note: Lets say you have 1 million users, a new attribute in the users table with one million user\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.)


I have Tomcat 7.0.27.0 with JDK 1.6

I am using tomcat only for Authentication and not for authorization

Following is the setup

context.xml

<Realm className="org.apache.catalina.realm.JDBCRealm"  
       connectionName="login"  
       connectionPassword="password"    
       connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:authdb"    
       driverName="oracle.jdbc.OracleDriver"        
       userTable="appusers"  
       userNameCol="username"              
       userCredCol="password"  
       allRolesMode="authOnly"/>  

web.xml

<security-constraint>  
    <web-resource-collection>  
        <web-resource-name>Protected Area</web-resource-name>  
        <url-pattern>/modules/*</url-pattern>  
        <url-pattern>/index.jsp</url-pattern>  
    </web-resource-collection>  
    <auth-constraint>
        <role-name>*</role-name>    
    </auth-constraint>
</security-constraint>     
<!--
security-role>
    <role-name>user</role-name>
security-role>
-->

I got it working by removing <security-role> block from web.xml &
putting auth-contraint with role-name as *

If you remove auth-contraint block from security-contraint then web context authentication itself will not be invoked !!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜