JDBC Glassfish 4 领域认证错误

JDBC Realm authentication bug Glassfish 4

好的,所以我在这上面花了很多时间,但看起来一切都设置正确,com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm 代码中有一个错误。

我正在尝试将基于表单的身份验证与程序化登录结合使用。我正在使用 Glassfish 4 和 JDK 1.8_40。当我在登录页面中输入我的详细信息时,容器试图将我定向到受保护的资源,但是它同时拒绝了我的访问 URL。对此进行调查后,我发现虽然登录成功,但容器未能验证我的登录并且未能将原则与任何角色相关联。这导致访问被拒绝错误。为了发现发生了什么,我将 glass fish 上的日志记录设置为正常,并发现堆栈跟踪中出现数组索引越界错误。

[2015-03-25T16:19:43.088+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783088] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm] [METHODNAME: isUserValid] [[
  Cannot validate user
java.lang.ArrayIndexOutOfBoundsException: 64
    at com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm.isUserValid(JDBCRealm.java:430)
    at com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm.authenticate(JDBCRealm.java:324)
    at com.sun.enterprise.security.ee.auth.login.JDBCLoginModule.authenticate(JDBCLoginModule.java:78)
    at com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:116)
    at com.sun.enterprise.security.BasePasswordLoginModule.login(BasePasswordLoginModule.java:146)
    at sun.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
    at javax.security.auth.login.LoginContext.access[=11=]0(LoginContext.java:195)
    at javax.security.auth.login.LoginContext.run(LoginContext.java:682)
    at javax.security.auth.login.LoginContext.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 com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:383)
    at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:241)
    at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:154)
    at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:695)
    at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:636)
    at org.apache.catalina.authenticator.AuthenticatorBase.doLogin(AuthenticatorBase.java:957)
    at org.apache.catalina.authenticator.AuthenticatorBase.login(AuthenticatorBase.java:939)
    at org.apache.catalina.connector.Request.login(Request.java:2245)
    at org.apache.catalina.connector.Request.login(Request.java:2224)
    at org.apache.catalina.connector.RequestFacade.login(RequestFacade.java:1113)
    at com.merrimansa.beans.UserAuthBean.login(UserAuthBean.java:80)
    at com.merrimansa.beans.UserAuthBean$Proxy$_$$_WeldClientProxy.login(Unknown Source)
    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:497)
    at javax.el.ELUtil.invokeMethod(ELUtil.java:326)
    at javax.el.BeanELResolver.invoke(BeanELResolver.java:536)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:269)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:147)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:818)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:745)
]]

[2015-03-25T16:19:43.150+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783150] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: setPolicyContext] [[
  [Web-Security] Policy Context ID was: __admingui/__admingui]]

[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
  [Web-Security] Codesource with Web URL: file:/__admingui/__admingui]]

[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
  [Web-Security] Checking Web Permission with Principals : null]]

[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: checkPermissionWithoutCache] [[
  [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/download/log/" "GET")]]

[2015-03-25T16:19:43.151+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.jmac.config] [tid: _ThreadID=33 _ThreadName=admin-listener(2)] [timeMillis: 1427296783151] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.jmac.config.GFServerConfigProvider] [METHODNAME: getEntry] [[
  getEntry for: HttpServlet -- GFConsoleAuthModule
    module class: org.glassfish.admingui.common.security.AdminConsoleAuthModule
    options: {loginErrorPage=/loginError.jsf, loginPage=/login.jsf}
    request policy: javax.security.auth.message.MessagePolicy@7a09d92
    response policy: null]]

[2015-03-25T16:19:43.182+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783182] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.realm.file.FileRealm] [METHODNAME: init] [[
  FileRealm : file=/etc/Glassfish4/glassfish4/glassfish/domains/domain1/config/admin-keyfile]]

[2015-03-25T16:19:43.182+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.realm] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783182] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.realm.file.FileRealm] [METHODNAME: init] [[
  FileRealm : jaas-context=ignore]]

[2015-03-25T16:19:43.184+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783184] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: initialize] [[
  Login module initialized: class com.sun.enterprise.security.auth.login.FileLoginModule]]

[2015-03-25T16:19:43.184+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=252 _ThreadName=admin-listener(9)] [timeMillis: 1427296783184] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: abort] [[
  JAAS authentication aborted.]]

[2015-03-25T16:19:43.197+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783197] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: login] [[
  JAAS login complete.]]

[2015-03-25T16:19:43.197+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783197] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.BasePasswordLoginModule] [METHODNAME: commit] [[
  JAAS authentication committed.]]

[2015-03-25T16:19:43.198+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.login] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783198] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.login.LoginContextDriver] [METHODNAME: doPasswordLogin] [[
  Password login succeeded for : Steve.Merriman@fluid.contitech.co.uk]]

[2015-03-25T16:19:43.207+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security.com.sun.enterprise.security.auth.login] [tid: _ThreadID=59 _ThreadName=http-listener-1(4)] [timeMillis: 1427296783207] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.auth.login.LoginContextDriver] [METHODNAME: doPasswordLogin] [[
  Set security context as user: Steve.Merriman@fluid.contitech.co.uk]]

[2015-03-25T16:19:43.467+0100] [glassfish 4.0] [FINE] [] [javax.enterprise.system.core.security] [tid: _ThreadID=56 _ThreadName=http-listener-1(1)] [timeMillis: 1427296783467] [levelValue: 500] [CLASSNAME: com.sun.enterprise.security.web.integration.WebSecurityManager] [METHODNAME: setPolicyContext] [[
  [Web-Security] Setting Policy Context ID: old = null ctxID = HSEManagmentApp/HSEManagmentApp]]

然后我调查了相关方法的源代码,发现一条评论说它可以接受最大长度 50,请参见下面的代码。我不确定这是否是一个转移注意力的问题,还是我刚刚在我的 JDBC 领域中设置了错误。任何对此的帮助将不胜感激,因为它占用了我的时间而且我离解决方案还差得很远。

private boolean isUserValid(String user, char[] password) {
401        Connection connection = null;
402        PreparedStatement statement = null;
403        ResultSet rs = null;
404        boolean valid = false;
405
406        try {
407            char[] hpwd = hashPassword(password);
408            connection = getConnection();
409            statement =  connection.prepareStatement(passwordQuery);
410            statement.setString(1, user);
411            rs = statement.executeQuery();
412            if (rs.next()) {
413                //Obtain the password as a char[] with a  max size of 50
414                Reader reader =  rs.getCharacterStream(1);
415                char[] pwd = new char[1024];
416                int noOfChars = reader.read(pwd);
417
418                /*Since pwd contains 1024 elements arbitrarily initialized,
419                    construct a new char[] that has the right no of char elements
420                    to be used for equal comparison*/
421                if (noOfChars < 0) {
422                    noOfChars = 0;
423                }
424                char[] passwd = new char[noOfChars];
425                System.arraycopy(pwd, 0, passwd, 0, noOfChars);
426                if (HEX.equalsIgnoreCase(getProperty(PARAM_ENCODING))) {
427                    valid = true;
428                    //Do a case-insensitive equals
429                    for(int i = 0; i < noOfChars; i ++) {
430                        if (!(Character.toLowerCase(passwd[i]) == Character.toLowerCase(hpwd[i]))) {
431                            valid = false;
432                            break;
433                        }
434                    }
435                } else {
436                    valid = Arrays.equals(passwd, hpwd);
437                }
438            }
439        } catch(SQLException ex) {
440                _logger.log(Level.SEVERE, "jdbcrealm.invaliduserreason", 
441                        new String [] {user,ex.toString()});
442            if (_logger.isLoggable(Level.FINE)) {
443                _logger.log(Level.FINE, "Cannot validate user", ex);
444            } 
445        } catch(Exception ex) {
446            _logger.log(Level.SEVERE, "jdbcrealm.invaliduser", user);
447            if (_logger.isLoggable(Level.FINE)) {
448                _logger.log(Level.FINE, "Cannot validate user", ex);
449            }
450        } finally {
451            close(connection, statement, rs);
452        }
453        return valid;
454    }

我已经附上了我的领域文件以防它是愚蠢的,但我已经尝试了几乎所有的组合。我还检查了数据库中的散列,它是正确的。唯一奇怪的是,如果我将散列设置为 'none' 那么它根本不起作用。

好的,我已经解决了这个问题以及我在身份验证方面遇到的所有其他问题,并希望 post 为未来面临这个问题的人提供一个答案。似乎正在使用的 SQL 查询正在用白色 space 填充数据库字段中任何未使用的 space ;因为我将密码字段设置为 nvarchar(500),这是返回的密码的长度,尽管 64 位之后的所有字符都是白色 space。这也导致了角色到组映射的问题,因为这是一个不同长度的字段,我无法更改字段长度来补偿,所以现在必须查找驱动程序或相关查询的问题。

此致