Android ImageLoader获取Http请求需带Cookie图片

来源:互联网 发布:新开的淘宝店怎么升级 编辑:程序博客网 时间:2024/06/08 17:24

前言

图片加载框架ImageLoader有缓存,获取图片过程中显示不同图片,异步加载等很多便利的功能。通过ImageLoader加载Server端图片十分方便,通过HTTP GET获取时,有时需要client提供一些必要的信息和session才能正常获取。
获取的过程也十分简单,在初始化完成ImageLoader之后,调用方法即可,如下:

ImageLoader.getInstance().displayImage(imageUri,                    (ImageView) layout.findViewById(R.id.imageItem),                    options, animateFirstListener);

但是有些情况下需要client提供一些参数和session,server端通过处理这些参数得到client所需的图片,然后才能正常返回响应图片。
在含有session_id的http请求,服务器返回200:
HttpRequest:
这里写图片描述

HttpResponse:
这里写图片描述

请求头中不含有Cookie:
HttpRequest:
这里写图片描述
HttpResponse:
这里写图片描述

这是因为服务端把客户端的用户信息存在了Session域中,如果不带cookie,服务端无法获取到用户信息,被认为是不合法的请求,Server端就不返回响应了(有的Server端也可能出于安全考虑)。

如何获取session_id

通过发送httprequest与服务端建立通讯,通过Sever返回的httpresponse的header获取session_id有时候是可行的,但是有些情况下Server端并不保留返回给Client端的Session或者这个Session在服务端存在的时间非常短暂,导致Client端拿着这个Session_id获取图片的时候服务端验证不通过,拒绝响应,这些情况下我们需要模拟一次用户登录,登录成功后服务器会记住用户的session,通过这个session_id就可以正常的获取Server端图片。

如何模拟用户登录

通过http post或者get请求,把用户信息传递给Server端,模拟用户登入,但是有些网站为了防止csrf攻击,往往需要用户登入过程提供csrf_token,这个token值一般是用户在访问登入页面时由Server端生成,返回给webclient端登入页面的,一般作为一个隐藏域存在form表单中:

<form class="oe_login_form" role="form" action="/web/login" method="post" onsubmit="this.action = this.action + location.hash">    <input name="csrf_token" value="c091f253d41f65f79ed3d6f21f255683d5efa7eao1476672733" type="hidden">    .....</form>

所以在模拟用户login时一般要抓取登入页面的csrf_token。
下面是一串Androidclient端的代码:

    private void getSessionInfo()    {        HttpHelper.get("/web?db="+Global.DB, new AsyncHttpResponseHandler() {            @Override            public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                HtmlElementUtil.getHeaderSession(headers);                String res = new String(responseBody);                List<String> result = HtmlElementUtil.match(res,"input","value");                if(result == null || result.size() == 0)                {                    return;//如果session没有过期那么就继续使用                }                RequestParams params = new RequestParams();                params.add("csrf_token",result.get(0).replace("/","").replace("\"",""));                params.add("db","pos");                params.add("login","admin");                params.add("password","admin");                params.add("redirect","");                HttpHelper.post("/web/login",params,new AsyncHttpResponseHandler(){                    @Override                    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {                        HtmlElementUtil.getHeaderSession(headers);                    }                    @Override                    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {                        String res = new String(responseBody);                    }                });            }            @Override            public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {            }        });    }

注:
HttpHelper是一个基于async-http的工具类。
web/db是服务端的数据库选择页面,服务端会通过临时session判断是否选择数据库,如果没有选择,会强制跳转到数据库选择页面。
跳转到登录页面之后,HtmlElementUtil.match(res,”input”,”value”)方法时自定义方法大致就是正则匹配所有的input标签,获取所有的value值(是一个list),通过value(list中包含csrf_token的值)便可以获取csrf_token。登入成功后通过HtmlElementUtil.getHeaderSession(headers)静态方法,从Server返回的Header数组中Cookie:session_id键值对获取session_id。

自定义ImageLoader请求头

//ImageLoader的初始化方法,ImageLoader采用单例模式,只需要初始化一次private void InitiateImgLoaderOpt() {        ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(getApplicationContext());        config.threadPriority(Thread.NORM_PRIORITY - 2);        config.denyCacheImageMultipleSizesInMemory();        config.diskCacheFileNameGenerator(new Md5FileNameGenerator());        config.diskCacheSize(50 * 1024 * 1024); // 50 MiB        config.tasksProcessingOrder(QueueProcessingType.LIFO);        config.writeDebugLogs(); // Remove for release app        config.imageDownloader(new ImageDownloader(this));        // Initialize ImageLoader with configuration.        ImageLoader.getInstance().init(config.build());    }public class ImageDownloader extends BaseImageDownloader {    public ImageDownloader(Context context) {        super(context);    }//ImageLoader图片加载httprequest设置方法    @Override    protected HttpURLConnection createConnection(String url, Object extra) throws IOException {        // Super...        HttpURLConnection connection = super.createConnection(url, extra);        connection.setRequestProperty("Cookie", Global.SESSION_ID);        connection.setRequestProperty("Connection", "keep-alive");        return connection;    }}//此代码设置Android view视图中的图片,animateFirstListener是加载状态的监听器ImageLoader.getInstance().displayImage(imageUri,                    (ImageView) layout.findViewById(R.id.imageItem),                    options, animateFirstListener);//通过复写监听器类的onLoadingStarted,onLoadingFailed,onLoadingComplete,onLoadingCancelled方法设置对应显示的图片 private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {        static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());        @Override        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {            if (loadedImage != null) {                ImageView imageView = (ImageView) view;                boolean firstDisplay = !displayedImages.contains(imageUri);                if (firstDisplay) {                    FadeInBitmapDisplayer.animate(imageView, 500);                    displayedImages.add(imageUri);                }            }        }        @Override        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {            String re = failReason.toString();        }    }

其中的自定义类ImageDownloader就是ImageLoader加载网络图片的http请求的构造器,此类需要继承BaseImageDownloader。通过复写基类的createConnection方法,在方法体重创建HttpURLConnection(图片请求连接)设置获取到的Cookie(Session_id),便可以正常加载Server端图片。

0 0
原创粉丝点击