我刚刚开始使用Java EE进行编程,我正在尝试使用基于表单的用户身份验证和 JBoss数据库登录模块实现一个简单的Web应用程序
当我运行我的网络应用程序并转到主页时,它会将我带到登录页面。到现在为止还挺好。但是当我提交用户名和密码时,登录失败,并在server.log
...
2016-01-28 14:22:37,028 TRACE [org.jboss.security] (default task-5) PBOX00236: Begin initialize method
2016-01-28 14:22:37,028 DEBUG [org.jboss.security] (default task-5) PBOX00281: Password hashing activated, algorithm: SHA-256, encoding: base64, charset: null, callback: null, storeCallBack: null
2016-01-28 14:22:37,028 TRACE [org.jboss.security] (default task-5) PBOX00262: Module options [dsJndiName: java:/PostgresHibrid, principalsQuery: select passwd from users where username=?, rolesQuery: select role, 'Roles' from userroles where username=?, suspendResume: true]
2016-01-28 14:22:37,029 TRACE [org.jboss.security] (default task-5) PBOX00240: Begin login method
2016-01-28 14:22:37,030 TRACE [org.jboss.security] (default task-5) PBOX00263: Executing query select passwd from users where username=? with username user0
2016-01-28 14:22:37,037 TRACE [org.jboss.security] (default task-5) PBOX00244: Begin abort method, overall result: false
2016-01-28 14:22:37,037 DEBUG [org.jboss.security] (default task-5) PBOX00206: Login failure: javax.security.auth.login.LoginException: PBOX00065: Error processing query
at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:202)
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:265)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:406)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:345)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:333)
at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:146)
at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verifyCredential(JAASIdentityManagerImpl.java:111)
at org.wildfly.extension.undertow.security.JAASIdentityManagerImpl.verify(JAASIdentityManagerImpl.java:82)
at io.undertow.security.impl.FormAuthenticationMechanism.runFormAuth(FormAuthenticationMechanism.java:124)
at io.undertow.security.impl.FormAuthenticationMechanism.authenticate(FormAuthenticationMechanism.java:96)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:339)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:356)
at io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:325)
at io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:138)
at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:113)
at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:106)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
at io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:33)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.postgresql.util.PSQLException: ERROR: relation "users" does not exist
Position: 20
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:622)
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:472)
at org.postgresql.jdbc.PgStatement.executeQuery(PgStatement.java:386)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:504)
at org.jboss.security.auth.spi.DatabaseServerLoginModule.getUsersPassword(DatabaseServerLoginModule.java:185)
... 50 more
2016-01-28 14:22:37,038 TRACE [org.jboss.security] (default task-5) PBOX00201: End isValid, result = false
2016-01-28 14:22:37,040 TRACE [org.jboss.security] (default task-5) PBOX00354: Setting security roles ThreadLocal: null ...
看起来应用程序无法在数据库中找到用户表。关于导致这种情况的任何想法?
我的配置信息如下。我使用的是WildFly 9.0.2 Final和PostgreSQL 9.3。
用户 postgres
postgres=# create user hibrid with password 'hibrid';
postgres=# alter role hibrid with createdb;
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------+-----------
hibrid | Create DB | {}
postgres | Superuser, Create role, Create DB, Replication | {}
postgres=# create database hibrid owner hibrid;
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
hibrid | hibrid | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
用户 hibrid
hibrid=> \c hibrid
hibrid=> CREATE TABLE users(username VARCHAR(255) PRIMARY KEY, passwd VARCHAR(255));
hibrid=> CREATE TABLE userroles(username VARCHAR(255), role VARCHAR(32));
hibrid=> \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+--------
public | userroles | table | hibrid
public | users | table | hibrid
(2 rows)
hibrid=> INSERT INTO users (username, passwd) values ('user0', 'Eu9N7XpGSO2ujqTCad1XT9U4qGhfDFNvLz9+53qpSaM=');
hibrid=> select * from users;
username | passwd
----------+----------------------------------------------
user0 | Eu9N7XpGSO2ujqTCad1XT9U4qGhfDFNvLz9+53qpSaM=
(1 row)
hibrid=> INSERT INTO userroles (username, role) values ('user0', 'ADMIN');
hibrid=> select * from userroles;
username | role
----------+-------
user0 | ADMIN
(1 row)
从https://jdbc.postgresql.org/download.html
下载最新的Postgres JDBC驱动程序。
我们假设驱动程序已下载到目录/home/hibrid/bin
并已命名
postgresql-9.4.1207.jar
。
启动WildFly CLI并连接到正在运行的WildFly实例
% ./jboss-cli.sh
[... /] connect
安装包含JDBC驱动程序的模块。
[... /] module add --name=org.postgres --resources=/home/hibrid/bin/postgresql-9.4.1207.jar --dependencies=javax.api,javax.transaction.api
在应用程序服务器上安装JDBC驱动程序
[... /] /subsystem=datasources/jdbc-driver=postgres:add(driver-name="postgres",driver-module-name="org.postgres",driver-class-name=org.postgresql.Driver)
{"outcome" => "success"}
standalone-full.xml
和standalone.xml
的数据源部分现在看起来像这样
<subsystem xmlns="urn:jboss:domain:datasources:3.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<datasource jndi-name="java:/PostgresHibrid" pool-name="PostgresHibrid" enabled="true">
<connection-url>jdbc:postgresql://localhost/postgres</connection-url>
<driver>postgres</driver>
<security>
<user-name>hibrid</user-name>
<password>hibrid</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="postgres" module="org.postgres">
<driver-class>org.postgresql.Driver</driver-class>
</driver>
</drivers>
</datasources>
</subsystem>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>HtmlAuth</web-resource-name>
<description>application security constraints </description>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/error.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>ADMIN</role-name>
</security-role>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<security-domain>hibridDomain</security-domain>
</jboss-web>