关于Java:JDBC Realm身份验证错误Glassfish 4

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位之后的所有字符都是空格。这也引起了组映射角色的问题,因为这是一个可变长度的字段,我无法更改字段长度以进行补偿,因此现在必须查找驱动程序或所涉及查询的问题。

致谢