Glassfish 5.1 上带有身份验证表单的空指针异常
null pointer exception with authentication form on Glassfish 5.1
根据官方文档,我有一个非常简单的 JEE 登录表单,它在本地 Glassfish 5.1 开发机器上运行良好。
https://docs.oracle.com/javaee/6/tutorial/doc/gkbaa.html
但是,当部署在集群实例中的生产环境中时,相同的 5.1 版本,当点击任何需要身份验证的页面时,我得到以下堆栈跟踪。
该领域是一个常规 "file" 领域。
Unexpected error forwarding or redirecting to login page
java.lang.NullPointerException
at com.sun.logging.LogCleanerUtil.neutralizeForLog(LogCleanerUtil.java:70)
at org.apache.catalina.core.ApplicationDispatcher.<init>(ApplicationDispatcher.java:197)
at org.apache.catalina.core.StandardContext.getRequestDispatcher(StandardContext.java:7382)
at org.apache.catalina.core.ApplicationContext.getRequestDispatcher(ApplicationContext.java:329)
at org.apache.catalina.core.ApplicationContextFacade.getRequestDispatcher(ApplicationContextFacade.java:249)
at org.apache.catalina.authenticator.FormAuthenticator.forwardToLoginPage(FormAuthenticator.java:473)
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:222)
at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1515)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:536)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:579)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:75)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:199)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:439)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:144)
at org.glassfish.grizzly.http.server.HttpHandler.run(HttpHandler.java:200)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:569)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:549)
at java.lang.Thread.run(Thread.java:748)
]]
我查看了LogCleanerUtilclass,应该是开源的
public static String neutralizeForLog(String message){
StringBuilder sb = new StringBuilder();
for(int offset = 0; offset < message.length(); ){
final int point = message.codePointAt(offset);
if(Character.isValidCodePoint(point)){
sb.append(encodeCharacter(point));
}
offset += Character.charCount(point);
}
return sb.toString();
}
由于 message
为空,因此出现空指针。
问题是为什么 message 是 null ?我们是在谈论日志消息吗?除了 OS 版本之外,与本地环境的唯一区别是在生产服务器上我使用 asadmin 命令创建了 glassfish 领域和整个集群。
这里是web.xml
<security-constraint>
<display-name>Admin Constraint</display-name>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/console/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Console Admin</description>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>console-realm</realm-name>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
好吧...经过一些调查后发现至少对我来说它似乎是一个错误。我已经在 glassfish 存储库中打开了一个 issue:
根据堆栈跟踪,StandardContext.java 在第 7382 行传递的 name
为空
// Construct a RequestDispatcher to process this request
return new ApplicationDispatcher
(wrapper, mappingForDispatch, uriCC.toString(), wrapperPath, pathInfo,
queryString, null);
因此,调用这些方法会导致空指针异常,因为如果您查看 ApplicationDispatcher.java 行
,生产中的日志级别为 FINE(因为尚未生产)
if (log.isLoggable(Level.FINE))
log.log(Level.FINE, "servletPath= " + neutralizeForLog(this.servletPath) + ", pathInfo= "
+ neutralizeForLog(this.pathInfo) + ", queryString= " + neutralizeForLog(queryString) + ", name= "
+ neutralizeForLog(this.name));
最终 neutralizeForLog
失败了,因为消息实际上是空的。
根据官方文档,我有一个非常简单的 JEE 登录表单,它在本地 Glassfish 5.1 开发机器上运行良好。
https://docs.oracle.com/javaee/6/tutorial/doc/gkbaa.html
但是,当部署在集群实例中的生产环境中时,相同的 5.1 版本,当点击任何需要身份验证的页面时,我得到以下堆栈跟踪。 该领域是一个常规 "file" 领域。
Unexpected error forwarding or redirecting to login page
java.lang.NullPointerException
at com.sun.logging.LogCleanerUtil.neutralizeForLog(LogCleanerUtil.java:70)
at org.apache.catalina.core.ApplicationDispatcher.<init>(ApplicationDispatcher.java:197)
at org.apache.catalina.core.StandardContext.getRequestDispatcher(StandardContext.java:7382)
at org.apache.catalina.core.ApplicationContext.getRequestDispatcher(ApplicationContext.java:329)
at org.apache.catalina.core.ApplicationContextFacade.getRequestDispatcher(ApplicationContextFacade.java:249)
at org.apache.catalina.authenticator.FormAuthenticator.forwardToLoginPage(FormAuthenticator.java:473)
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:222)
at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1515)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:536)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:579)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:75)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:199)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:439)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:144)
at org.glassfish.grizzly.http.server.HttpHandler.run(HttpHandler.java:200)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:569)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:549)
at java.lang.Thread.run(Thread.java:748)
]]
我查看了LogCleanerUtilclass,应该是开源的
public static String neutralizeForLog(String message){
StringBuilder sb = new StringBuilder();
for(int offset = 0; offset < message.length(); ){
final int point = message.codePointAt(offset);
if(Character.isValidCodePoint(point)){
sb.append(encodeCharacter(point));
}
offset += Character.charCount(point);
}
return sb.toString();
}
由于 message
为空,因此出现空指针。
问题是为什么 message 是 null ?我们是在谈论日志消息吗?除了 OS 版本之外,与本地环境的唯一区别是在生产服务器上我使用 asadmin 命令创建了 glassfish 领域和整个集群。
这里是web.xml
<security-constraint>
<display-name>Admin Constraint</display-name>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/console/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Console Admin</description>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>console-realm</realm-name>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/loginError.xhtml</form-error-page>
</form-login-config>
</login-config>
好吧...经过一些调查后发现至少对我来说它似乎是一个错误。我已经在 glassfish 存储库中打开了一个 issue:
根据堆栈跟踪,StandardContext.java 在第 7382 行传递的 name
为空
// Construct a RequestDispatcher to process this request
return new ApplicationDispatcher
(wrapper, mappingForDispatch, uriCC.toString(), wrapperPath, pathInfo,
queryString, null);
因此,调用这些方法会导致空指针异常,因为如果您查看 ApplicationDispatcher.java 行
,生产中的日志级别为 FINE(因为尚未生产) if (log.isLoggable(Level.FINE))
log.log(Level.FINE, "servletPath= " + neutralizeForLog(this.servletPath) + ", pathInfo= "
+ neutralizeForLog(this.pathInfo) + ", queryString= " + neutralizeForLog(queryString) + ", name= "
+ neutralizeForLog(this.name));
最终 neutralizeForLog
失败了,因为消息实际上是空的。