zoukankan      html  css  js  c++  java
  • UniversalImageLoader加密磁盘缓存

          感谢CSDN博主Mr_甘 的博客android imageloader加密解密图片(地址:http://blog.csdn.net/gan303/article/details/50266569)

    当使用网络图片缓存到本地时,基于安全考虑需要加密缓存到本地的数据,加上使用UIL已经很久了,并且很好用,所以决定扩展UIL支持加密本地缓存。开始干活了!!!

      在ImageLoaderConfiguration中找到imageDecoder和diskCache,imageDecoder用于提供读取数据生成Bitmap的接口,diskCache提供磁盘缓存的接口;就在这两个方面下功夫了。加密技术我选择javax下面CipherInputStream,提高效率,如果不满足你的需求可以自定义InputStream,重写read函数在(read函数里面进行加解密操作)就可以。这些前提就是你已经成功配置UniversalImageLoader库(包含需要的权限之类的)

      1(加密):继承UnlimitedDiskCache并重写save函数,save函数的功能就是将需要缓存到本地的数据保存在本地,当然我们只加密网络缓存图片,加密操作就是将原来的InputStream转化成加密的CipherInputStream。

    package com.common.cipher;
    
    import android.util.Log;
    
    import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
    import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
    import com.nostra13.universalimageloader.utils.IoUtils;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.crypto.CipherInputStream;
    
    /**
     * 作者:徐仕海 on 2016/7/25 0025 14:47
     * <p> 加密图片磁盘缓存
     * 邮箱:1056483075@qq.com
     */
    
    public class CipherUnlimitedDiskCache extends UnlimitedDiskCache {
    
    
        public CipherUnlimitedDiskCache(File cacheDir) {
            super(cacheDir);
        }
    
        public CipherUnlimitedDiskCache(File cacheDir, File reserveCacheDir) {
            super(cacheDir, reserveCacheDir);
        }
    
        public CipherUnlimitedDiskCache(File cacheDir, File reserveCacheDir, FileNameGenerator fileNameGenerator) {
            super(cacheDir, reserveCacheDir, fileNameGenerator);
        }
    
        @Override
        public boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException {
            Log.e("TAG", "保存到本地");
            InputStream inputStream;
            /**
             * 本地文件的缓存就不加密了
             */
            if (imageUri.startsWith("http")) {
                try {
                    inputStream = new CipherInputStream(imageStream, CipherImage.getInstance().getEncryptCipher());
                } catch (Exception e) {
                    imageStream.close();
                    e.printStackTrace();
                    return false;
                }
            } else {
                inputStream = imageStream;
            }
            return super.save(imageUri, inputStream, listener);
        }
    }

      2(解密):加密了图片接下来就是解密加密过后的数据,继承BaseImageDecoder,并重写getImageStream函数,当然我们也只解密网络图片,解密操作就是将InputStream转化成解密的CipherInputStream。

    package com.common.cipher;
    
    import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
    import com.nostra13.universalimageloader.core.decode.ImageDecodingInfo;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.crypto.CipherInputStream;
    
    /**
     * 作者:徐仕海 on 2016/7/25 0025 11:20
     * <p> 解密图片解码器
     * 邮箱:1056483075@qq.com
     */
    
    public class CipherImageDecoder extends BaseImageDecoder {
        public CipherImageDecoder(boolean loggingEnabled) {
            super(loggingEnabled);
        }
    
        @Override
        protected InputStream getImageStream(ImageDecodingInfo decodingInfo) throws IOException {
            InputStream imageStream = super.getImageStream(decodingInfo);
            /**
             * 只解密网络下载的图片,其他的途径的图片不用加密所以就不用解密,加解密手段用的是Java的加解密输入流
             */
            if (decodingInfo.getOriginalImageUri().startsWith("http")) {
                CipherInputStream in = null;
                try {
                    in = new CipherInputStream(imageStream, CipherImage.getInstance().getDecryptCipher());
                } catch (Exception e) {
                    e.printStackTrace();
                    imageStream.close();
                }
                return in;
            }
            return imageStream;
        }
    
    }

      3(加解密Cipher对象):为了方便使用且方便修改密钥和加解密算法新建一个CipherImage类,他主要用来配置密钥和算法,生成加解密的Cipher对象供创建CipherInputStream类使用

    package com.common.cipher;
    
    import java.security.InvalidKeyException;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    
    import javax.crypto.Cipher;
    import javax.crypto.NoSuchPaddingException;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * 作者:徐仕海 on 2016/7/26 0026 10:18
     * <p>主要提供加密密钥,加解密算法,加密Cipher对象,解密Cipher对象
     * 邮箱:1056483075@qq.com
     */
    public class CipherImage {
        private static CipherImage ourInstance = new Builder().build();
    
        public static CipherImage getInstance() {
            return ourInstance;
        }
    
        private CipherImage() {}
    
        /**
         * 加解密图片的密钥
         */
        private String key;
    
        /**
         * 加解密算法
         */
        private String algorithm;
    
        /**
         * 获取解密Cipher
         *
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         */
        public Cipher getDecryptCipher() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
            byte[] str = key.getBytes();
            Key key = new SecretKeySpec(str, 0, str.length, algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher;
        }
    
        /**
         * 获取加密Cipher
         *
         * @return
         * @throws NoSuchPaddingException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         */
        public Cipher getEncryptCipher() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
            byte[] str = key.getBytes();
            Key key = new SecretKeySpec(str, 0, str.length, algorithm);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return cipher;
        }
    
    
        /**
         * 构造器
         */
        public static class Builder {
            private String key, algorithm;
    
            public Builder() {
                key = "123456";//默认密钥
                algorithm = "RC4";//默认加解密算法
            }
    
            public Builder cipherKey(String key) {
                this.key = key;
                return this;
            }
    
            public Builder cipherAlgorithm(String algorithm) {
                this.algorithm = algorithm;
                return this;
            }
    
            public CipherImage build() {
                if (ourInstance == null) {
                    ourInstance = new CipherImage();
                }
                ourInstance.algorithm = algorithm;
                ourInstance.key = key;
                return ourInstance;
            }
        }
    }

      功能实现完毕,接下来该试试如何使用了。首先必须启用缓存到磁盘,在设置图片解码器和磁盘缓存,这样每张网络图片缓存在磁盘上的数据都是加密的都是安全的。

    DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder().cacheOnDisk(true).cacheInMemory(true).build();
            ImageLoaderConfiguration configuration = null;
            configuration = new ImageLoaderConfiguration.Builder(this)
                    .imageDecoder(new CipherImageDecoder(true))
                    .diskCache(new CipherUnlimitedDiskCache(getExternalCacheDir()))
                    .defaultDisplayImageOptions(displayImageOptions)
                    .build();
     ImageLoader.getInstance().init(configuration);
     final ImageView imageView = (ImageView) findViewById(R.id.imageView);
     ImageLoader.getInstance().displayImage("http://desk.fd.zol-img.com.cn/t_s1920x1080c5/g5/M00/0D/0D/ChMkJ1eV_E2IMTEQABERSEVD0poAAT0hAID5McAERFg559.jpg", imageView);

     当然如果你不喜欢默认的密钥123456或者默认的加解密算法RC4,可以更新密钥和算法,只要在图片保存之前都会有效

    new CipherImage.Builder()
                    .cipherAlgorithm("RC4")
                    .cipherKey("dhghd")
                    .build();

     本文示例工程的地址https://files.cnblogs.com/files/xushihai/CipherUIL.rar

  • 相关阅读:
    关于安卓9patch图片的探究
    android中系统时间
    android中的对话框
    swing界面刷新问题
    android中的xml解析全解
    android中listView下拉刷新
    次小生成树(poj 1679)
    poj 2312(bfs+priority_queue)
    poj 2060(最小路径覆盖)
    poj 1734 (最小环)
  • 原文地址:https://www.cnblogs.com/xushihai/p/5707068.html
Copyright © 2011-2022 走看看