AspectJ截获操作

时间:2022-10-16 16:39:44
package com.example.aspectjandroidtest;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.http.util.EncodingUtils;

import com.facebook.crypto.Crypto;
import com.facebook.crypto.Entity;
import com.facebook.crypto.keychain.SharedPrefsBackedKeyChain;
import com.facebook.crypto.util.SystemNativeCryptoLibrary;

public aspect FileAspectJ {

	private boolean isEncryption = true;
	//使用秘钥链和原生库的默认实现,来创建一个新的加密对象
	Crypto crypto = new Crypto(
			new SharedPrefsBackedKeyChain(MainActivity.context),
			new SystemNativeCryptoLibrary());

	//创建应用文件的切点集合
	pointcut openFileOutput(String filename,int mode) : !within(FileAspectJ) && args(filename,mode) && call(* openFileOutput(..));
	after (String filename,int mode) returning : openFileOutput(filename, mode){
		//System.out.println("fx Aspectj openFile is start");
		byte[] buffer;
		try {
			System.out.println("fx Aspectj openFileName"+filename);
			buffer = filename.getBytes("UTF8");
			FileOutputStream fileOutputStream = null;
			try {
				//记录本应用加密过的文件
				fileOutputStream = MainActivity.context.openFileOutput("fileList",
						MainActivity.context.MODE_APPEND);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				fileOutputStream.write(buffer);
				fileOutputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	//读取应用文件的切点集合
		pointcut openFileInput(String filename) : !within(FileAspectJ) && args(filename) && call(* openFileInput(..));
		before(String filename) : openFileInput(filename){

			String result = "";
			try {
				FileInputStream fileInputStream = MainActivity.context.openFileInput("fileList");
				int bufferSize = 0;
				try {
					bufferSize = fileInputStream.available();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} // 取得输入流的字节长度
				byte buffer[] = new byte[bufferSize];
				try {
					fileInputStream.read(buffer);
					fileInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				result = EncodingUtils.getString(buffer, "UTF-8");
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//判断文件是否加密过
			if(result.indexOf(filename) == -1){
				isEncryption = false;//未加密
				System.out.println("fx 文件未加密");
			}else{
				isEncryption = true;//已加密
				System.out.println("fx 文件已加密");
			}
		}

		//截获到File的new操作
		pointcut filePointcut(String pathname ) :  !within(FileAspectJ) && args(pathname) && call(java.io.File.new(..));
		before(String pathname ) : filePointcut(pathname) {
			System.out.println("fx pathname is " + pathname);
		}

	//写文件切点的集合
	pointcut writePointcut(FileOutputStream fileStream, byte[] buffer) : !within(FileAspectJ) && target(fileStream)&& args(buffer) && call(* write(..));
	void around(FileOutputStream fileStream, byte[] buffer) : writePointcut(fileStream, buffer) {
		System.out.println("fx Aspectj write is start");
		//检查加密功能是否可用
		//如果Android没有正确载入库,则此步骤可能失败
		if (!crypto.isAvailable()) {
			System.out.println("return error");
			return;
		}
		OutputStream fbFileStream = new BufferedOutputStream(fileStream);
		try {
			//创建输出流,当数据写入流的时候进行加密,并将加密后的数据输出到文件
			OutputStream outputStream = crypto.getCipherOutputStream(
					fbFileStream, new Entity("test"));
			outputStream.write(buffer);
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//读文件切点集合
	pointcut readPointcut(FileInputStream fileStream, byte[] buffer) : !within(FileAspectJ) && target(fileStream)&& args(buffer) && call(* read(..));
	int around(FileInputStream fileStream, byte[] buffer) : readPointcut(fileStream, buffer) {
		System.out.println("fx Aspectj read is start");
		int bufferSize = 0;
		if(isEncryption==false){
			return 0;
		}
		try {
			//文件流解密操作
			InputStream inputStream = crypto.getCipherInputStream(fileStream,	new Entity("test"));
			bufferSize = inputStream.available(); // 取得输入流的字节长度
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
	        byte[] data = new byte[1024];
			int len;
			 if (inputStream != null) {
		            try {
		                while ((len = inputStream.read(data)) != -1) {
		                    outputStream.write(data, 0, len);
		                }
		                data = outputStream.toByteArray();
		            } catch (IOException e) {
		            }
		        }
			 for(int i = 0;i<data.length;i++) {
				 buffer[i] = data[i];
			 }
			inputStream.close();
			outputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return bufferSize;
	}

}