Centos7+Tomcat8验证码不显示问题

字数 335阅读 460

Centos7+Tomcat8验证码不显示问题

问题描述:

部署的项目在Mac下运行正常,验证码显示正常,但是把项目部署到正式环境上之后发现验证码不显示,直接访问验证码链接报错400缺少open-sans字体,添加字体不能解决问题,log日志没有报错信息显示。

分析:

项目中并没有使用这个字体,切生成二维码的字体也不是这个字体,所以可以断定肯定不是字体的问题,对比tomcat目录发现服务器上tomcat的temp目录被删了,创建一个temp文件刷新页面二维码显示正常

哪生成二维码图片的显示和tomcat下的temp文件存不存有什么关系呢?

二维码生成代码如下:

OutputStream out = response.getOutputStream();
ImageIO.write(image, "JPEG", out);
out.close();

查看ImageIO.write源码如下:

  public static boolean write(RenderedImage im,String formatName,OutputStream output) throws IOException {
        if (output == null) {
            throw new IllegalArgumentException("output == null!");
        }
        ImageOutputStream stream = null;
        try {
            stream = createImageOutputStream(output);//创建图片输出流
        } catch (IOException e) {
            throw new IIOException("Can't create output stream!", e);
        }

        try {
            return doWrite(im, getWriter(im, formatName), stream);
        } finally {
            stream.close();
        }
    }

查看createImageOutputStream()源码如下:

public static ImageOutputStream createImageOutputStream(Object output)
       throws IOException {
       if (output == null) {
           throw new IllegalArgumentException("output == null!");
       }

       Iterator iter;
       // Ensure category is present
       try {
           iter = theRegistry.getServiceProviders(ImageOutputStreamSpi.class,
                                                  true);
       } catch (IllegalArgumentException e) {
           return null;
       }

       boolean usecache = getUseCache() && hasCachePermission();//判断是否会使用cache文件

       while (iter.hasNext()) {
           ImageOutputStreamSpi spi = (ImageOutputStreamSpi)iter.next();
           if (spi.getOutputClass().isInstance(output)) {
               try {
                   return spi.createOutputStreamInstance(output,
                                                         usecache,
                                                         getCacheDirectory());
               } catch (IOException e) {
                   throw new IIOException("Can't create cache file!", e);
               }
           }
       }

       return null;
   }

查看hasCachePermission()源码如下:

private static boolean hasCachePermission() {
    Boolean hasPermission = getCacheInfo().getHasPermission();

    if (hasPermission != null) {
        return hasPermission.booleanValue();
    } else {
        try {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                File cachedir = getCacheDirectory();
                String cachepath;
                /*
                 * 写得也很清楚,如果自己设置了 setCacheDirectory 那么会使用自定义的,否则调用getTempDir()
                 */
                if (cachedir != null) {
                    cachepath = cachedir.getPath();
                } else {
                    cachepath = getTempDir();

                    if (cachepath == null || cachepath.isEmpty()) {
                        getCacheInfo().setHasPermission(Boolean.FALSE);
                        return false;
                    }
                }

                // we have to check whether we can read, write,
                // and delete cache files.
                // So, compose cache file path and check it.
                String filepath = cachepath;
                if (!filepath.endsWith(File.separator)) {
                    filepath += File.separator;
                }
                filepath += "*";

                security.checkPermission(new FilePermission(filepath, "read, write, delete"));
            }
        } catch (SecurityException e) {
            getCacheInfo().setHasPermission(Boolean.FALSE);
            return false;
        }

        getCacheInfo().setHasPermission(Boolean.TRUE);
        return true;
    }
}

查看getTempDir()源码如下:

/** 
  * Returns the default temporary (cache) directory as defined by the 
  * java.io.tmpdir system property. 
  */  
 private static String getTempDir() {  
     GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");  
     return (String)AccessController.doPrivileged(a);  
 }  

从上面代码可以看出来是读取了变量java.io.tmpdir,而我们tomcat启动的时候会tomcat 启动的时候,调用jvm会设置 java.io.tmpdir参数 使用temp文件夹,所以生成图片的程序tomcat目录下必须要有temp文件夹

image.png

推荐阅读更多精彩内容