我的环境配置:RHEL6.5+tomcat6+jdk1.6
今天遇到一个奇怪的现象,我的tomcat启动起来之后,网站无法显示验证码,导致无法登陆。我的tomcat启动过程是这样的:
我有一个进程守护的程序monitor,当开机的时候用自启动脚本的方式启动monitor,然后monitor检测tomcat进程是否启动如果没有启动,就将tomcat进程启动起来。
流程如下图所示:
使用这样的方式启动的tomcat无法显示验证码。F12打开调试器出现了错误
<html><head><title>Apache Tomcat/6.0.20 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 500 - </h1><HR size="1" noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></p><p><b>exception</b> <pre>
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/sun/image/codec/jpeg/ImageFormatException
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1259)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
main.com.ieslab.util.XSSFilter.doFilter(XSSFilter.java:24)
main.com.ieslab.util.AccessControlFilter.doFilter(AccessControlFilter.java:72)
org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(Delegatin
网上说法:封装了验证码生成的类使用JPEGCodec类生成验证码的图片。而图像处理JPEGCodec类已经从Jdk1.7移除。需要用ImageIO.write重写,原文链接:https://my.oschina.net/zb0423/blog/86507
我用的是jdk1.6,所以我的错误不应该是JPEGCodec类引起的,然后抱着试试看的态度用ImageIO.write重写,可验证码还是无法显示。
更加奇怪的是,我手动从终端执行./catalina.sh run
启动动的tomcat却能显示验证码。倒腾了一上午还是没有解决问题,最后我用非root用户执行./catalina.sh run
,问题重现:验证码无法显示。恍然大悟,应该是权限问题导致的,马上做实验。我先用root账户登录,执行./catalina.sh run
,验证码能显示。然后用非root用户user01登录,执行./catalina.sh run
,验证码就无法显示了。
问题的原因已经找到:tomcat进程没有用root用户启动,用ps命令查看了一下tomcat进程,确实不是root用户。
[user01@RHEL6 ~]$ ps -ef |grep java | grep -v grep | grep tomcat
user01 1857 1 89 14:16 ? 00:00:22 /usr/bin/java -Djava.util.logging.config.file=/usr/appsoft/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/appsoft/tomcat/endorsed -classpath :/usr/appsoft/tomcat/bin/bootstrap.jar -Dcatalina.base=/usr/appsoft/tomcat -Dcatalina.home=/usr/appsoft/tomcat -Djava.io.tmpdir=/usr/appsoft/tomcat/temp -Djava.awt.headless=true org.apache.catalina.startup.Bootstrap start
user01 1931 1 99 14:16 ? 00:00:09 /usr/bin/java -Djava.util.logging.config.file=/usr/appsoft/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/appsoft/tomcat/endorsed -classpath :/usr/appsoft/tomcat/bin/bootstrap.jar -Dcatalina.base=/usr/appsoft/tomcat -Dcatalina.home=/usr/appsoft/tomcat -Djava.io.tmpdir=/usr/appsoft/tomcat/temp -Djava.awt.headless=true org.apache.catalina.startup.Bootstrap start
那如何让自启动的程序是以root用户启动的呢?
其实很简单将自启动脚本的属主改为root用户,赋予可执行权限,并创建自启动脚本链接
#chown -R root:root /sbin/mystart
#chmod +x /sbin/mystart
#ln -s /sbin/iesstart /etc/rc5.d/S999mystart
其中mystart为我的自启动脚本文件。这样问题得以解决!!!
可能的原因二:
当使用ps -ef |grep java | grep -v grep | grep tomcat
查看没有显示验证码的tomcat进程时,可以看出此时使用的java路径为/usr/bin/java,这个java为系统自带的。
当查看正常显示的tomcat进程时,此时使用的java为/usr/appsoft/jdk1.6.0_45/jre/bin/java,这个路径为自己安装的java路径。
因此可以分析出验证码无法显示是因为使用了系统自带的java,因此将系统自带的java卸载即可。