日期:2014-05-16  浏览次数:20794 次

apache安全加固后ie8下png图片显示异常
前两天遇到一个问题,线上报表系统的图片显示不出来了.
这个问题只出现在ie8下.对于其他浏览器都显示正常.
试着将报表图片的地址直接在ie中访问
引用

/preview?__sessionId=20110911_170334_597&__imageid=custom1666453a13257b916471.png

ie会弹出一个文件然你下载,将下载的文件改成xxx.png后图片正常显示.
由此可见ie8没有正确解析资源.
联想到前几天对apache做了安全加固,打了一个防止xss漏洞的配置.
会不会是这个引起的呢?配置如下:
引用

<IfModule mod_headers.c>
        Header set X-Content-Type-Options "nosniff"
        Header set X-XSS-protection "1;mode=block"
        RequestHeader unset Range
</IfModule>

将这个配置去掉后,图片可以正常显示.于是可以认定是配置引起的这个故障.
但是为什么会引起这个故障呢?
而且安全配置是不能修改的,所以要解决这个问题我们就必须要从别的方面来着手.
先让我们看看apache干了点什么吧!
这段配置主要是防止xss攻击的
引用

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的。XSS属于被动式的攻击,因为其被动且不好利用,所以许多人常忽略其危害性。

做了这个配置后,如果是ie8访问,apache会自动在请求头上加上
X-Content-Type-Options "nosniff"
X-XSS-protection "1;mode=block"
这两个配置.
第一个配置是告诉浏览器,如果遇到未知文件类型,不要去自动解析.
问题就出在这了,birt对于图片的请求content_type返回的是个image的值,这个值ie8是无法确定解析类型的,如果允许ie8自动分析文件确定解析图片,那么图片是可以正常显示的,但是禁止后,ie8无法确定的文件类型就不会再解析,页面上就会显示一个红叉叉.

既然已经了解了前因后果,那么只要做出相对应的操作,就可以解决这个问题.
最开始的想法是在filter中设置一下response,将content-type设置为image/x-png
但是发现这么做无效,浏览器返回的response还是image类型.

G了一下,发现了这么一段话.
引用

response.setContentType指定 HTTP 响应的编码,同时指定了浏览器显示的编码.
response.setCharacterEncoding设置HTTP 响应的编码,如果之前使用response.setContentType设置了编码格式,则使用response.setCharacterEncoding指定的编码格式覆盖之前的设置.与response.setContentType相同的是,调用此方法,必须在getWriter执行之前或者response被提交之前.

看来在别的地方contenttype已经被修改过了,而且随后还调用了getwrite.
莫有办法,只好一步步的dug了,顺藤摸瓜.让我发现了这么一段.
/*************************************************************************************
 * Copyright (c) 2004 Actuate Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Actuate Corporation - Initial implementation.
 ************************************************************************************/

package org.eclipse.birt.report.service.actionhandler;

import java.util.regex.Pattern;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.birt.report.context.IContext;
import org.eclipse.birt.report.service.actionhandler.AbstractBaseActionHandler;
import org.eclipse.birt.report.service.api.InputOptions;
import org.eclipse.birt.report.soapengine.api.GetUpdatedObjectsResponse;
import org.eclipse.birt.report.soapengine.api.Operation;
import org.eclipse.birt.report.utility.ParameterAccessor;

abstract public class AbstractRenderImageActionHandler
		extends
			AbstractBaseActionHandler
{

	public AbstractRenderImageActionHandler( IContext context,
			Operation operation, GetUpdatedObjectsResponse response )
	{
		super( context, operation, response );
	}

		public void __execute( ) throws Exception
	{
		
context.getResponse( ).setContentType( "image" ); //$NON-NLS-1$
		
		
		String imageId = context.getRequest( ).getParameter(
				ParameterAccessor.PARAM_IMAGEID );
		ServletOutputStream out;
		String docName = null;// TODO: Do we need document name?

		InputOptions options = new InputOptions( );
		options.setOption( InputOptions.OPT_REQUEST, context.getRequest( ) );
		out = co