JDBC Realm authentication bug Glassfish 4
好,所以我花了很多时间,但是似乎所有设置都正确,并且com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm代码中存在错误。
我正在尝试通过编程式登录使用基于表单的身份验证。我正在使用Glassfish 4和JDK 1.8_40。当我在登录页面中输入我的详细信息时,容器会尝试将我定向到受保护的资源,但是,它使我无法使用同一URL进行访问。经过调查,我发现尽管登录成功,但容器仍无法验证我的登录名,并且未能将该原理与任何角色相关联。这导致访问被拒绝错误。为了发现正在发生的事情,我将玻璃鱼的记录设置为精细,并发现了在堆栈跟踪中看到的数组索引超出范围错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | [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$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 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$9.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.access$100(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领域中设置了错误。在这方面的任何帮助将不胜感激,因为它占用了我的时间,而且我离解决方案还很近。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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",则它根本不起作用。
好吧,我已经解决了这个问题,并且我通过身份验证解决了所有其他问题,并想为将来遇到此问题的人们提供答案。似乎正在使用的SQL查询正在用空格填充数据库字段中任何未使用的空间,因此;因为我将密码字段设置为nvarchar(500),这是返回的密码的长度,尽管64位之后的所有字符都是空格。这也引起了组映射角色的问题,因为这是一个可变长度的字段,我无法更改字段长度以进行补偿,因此现在必须查找驱动程序或所涉及查询的问题。
致谢