JDBC tomcat 中的领域配置

JDBC Realm configuration in tomcat

我正在尝试配置 tomcat 以使用 SQL 服务器进行身份验证。我修改了 server.xml 如下:

<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"/> 

    <!--This is only applicable for Tomcat 8.5 and higher version with SQL server authentication-->
        <Realm className="org.apache.catalina.realm.JDBCRealm"
          driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
    connectionURL="jdbc:sqlserver://xxx.xx.xxx.xxx:1433;databaseName=xxxx" connectionName="user" connectionPassword="password"  userTable="xx" userNameCol="username" userCredCol="password"/>
</Realm>

但是每次我尝试验证时都会收到以下错误:

SEVERE: Exception performing authentication com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near the keyword 'null'. at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:258) at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1535) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:467) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:409) at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151) at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:219) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:199) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:331) at org.apache.catalina.realm.JDBCRealm.getRoles(JDBCRealm.java:601) at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:404) at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:326) at org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:193) at org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:158) at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:84) at org.apache.catalina.authenticator.AuthenticatorBase.authenticate(AuthenticatorBase.java:700) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:599) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source)

Sep 21, 2017 12:00:59 PM org.apache.catalina.realm.JDBCRealm getRoles SEVERE: Exception performing authentication com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near the keyword 'null'. at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:258) at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1535) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:467) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:409) at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151) at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:219) at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:199) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:331) at org.apache.catalina.realm.JDBCRealm.getRoles(JDBCRealm.java:601) at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:404) at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:326) at org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:193) at org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:158) at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:84) at org.apache.catalina.authenticator.AuthenticatorBase.authenticate(AuthenticatorBase.java:700) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:599) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source)

我已经把mssql-jdbc-6.2.1.jre8.jar放到了lib文件夹里。

您的问题似乎是您没有指定 table 角色分配给用户。根据 Tomcat documentation 关于 JDBC 领域:

  • There must be a table, referenced below as the user roles table, that contains one row for every valid role that is assigned to a particular user. It is legal for a user to have zero, one, or more than one valid role.
  • The user roles table must contain at least two columns (it may contain more if your existing applications required it):
    • Username to be recognized by Tomcat (same value as is specified in the users table).
    • Role name of a valid role associated with this user

异常堆栈也证实了这样的猜测

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:331)
at org.apache.catalina.realm.JDBCRealm.getRoles(JDBCRealm.java:601)
at org.apache.catalina.realm.JDBCRealm.authenticate(JDBCRealm.java:404)

因此,要克服此类问题,您应该像这样指定角色 table userRoleTable 和角色名称列 roleNameCol

<Realm className="org.apache.catalina.realm.JDBCRealm"
       driverName="org.gjt.mm.mysql.Driver"
       connectionURL="jdbc:mysql://localhost/authority?user=dbuser&amp;
       password=dbpass"
       userTable="users" userNameCol="user_name" userCredCol="user_pass"
       userRoleTable="user_roles" roleNameCol="role_name"/>

希望对您有所帮助!