• 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

  • 相关阅读:
    Microsoft Enterprise Library 5.0 系列(二) Cryptography Application Block (初级)
    Microsoft Enterprise Library 5.0 系列(五) Data Access Application Block
    Microsoft Enterprise Library 5.0 系列(八) Unity Dependency Injection and Interception
    Microsoft Enterprise Library 5.0 系列(九) Policy Injection Application Block
    Microsoft Enterprise Library 5.0 系列(三) Validation Application Block (高级)
    软件研发打油诗祝大家节日快乐
    从挖井的故事中想到开发管理中最容易忽视的几个简单道理
    ITIL管理思想的执行工具发布
    管理类软件设计“渔”之演化
    20070926日下午工作流与ITILQQ群 事件管理 讨论聊天记录
  • 原文地址:https://www.cnblogs.com/xushihai/p/5707068.html
Copyright © 2020-2023  润新知