1. 文件夹解密阐明

只有加密的文件夹才须要解密,同一用户在查看同一加密文件夹或者是外面的文件/文件夹,每次胜利校验明码后,再次查看同一加密文件夹或外面的文件/文件夹,不必输出明码,72个小时后查看才须要输出明码;(除非有批改明码,如有批改明码,则须要从新输出,批改后第一次胜利验证明码后再开始计算72小时)。

注:校验是否72小时是在客户端实现

2. 文件夹解密过程

1) 解密过程阐明

咱们在拜访加密的文件时:

先去依据scopeToken和path去本地数据库(sqlite)查找该文件先前是否有保留解密明码
如果存在的话,则会校验该条数据是否超过72小时,在没有超过72小时的状况下就拿这条数据的明码拜访接口Get:/api/plugin/wangpan/folders/:path 校验明码是否正确:
正确的话进入文件夹详情,并更新该文件夹本地保留的明码和批改工夫;
谬误须要从新输出明码并拜访接口校验该明码是否正确;
校验数据是超过72小时的状况下,须要输出明码并拜访接口校验该明码是否正确:
在正确的状况下更新该文件夹本地保留的明码和批改工夫,并插入该文件的明码缓存信息到数据库;
否则提醒用户明码谬误,从新输出;

2) 次要代码实现

/** * 文件 */public class HomeFragment extends BaseMVPDBFragment<FragmentHomeBinding, HomeContract.View, HomePresenter> implements HomeContract.View {    ...         /**     * 初始化列表     */    private void initRv() {        homeFileAdapter = new HomeFileAdapter(1, true);        binding.rrv.setAdapter(homeFileAdapter)                .setOnRefreshAndLoadMoreListener(refreshLoadMoreListener);        homeFileAdapter.setOnItemClickListener((adapter, view, position) -> {            mFileBean = homeFileAdapter.getItem(position);            if (mFileBean.getType() == 0 && homeFileAdapter.getSelectedSize() <= 0) { // 如果是文件夹,且没有处于编辑状态                if (mFileBean.getRead() == 1) {  // 有读权限                    if (mFileBean.getIs_encrypt() == 1) { // 加密文件                        mPresenter.getFolderPwdByScopeTokenAndPath(Constant.scope_token, mFileBean.getPath());                    } else {  // 非加密文件                        filePwd = "";                        toFolderDetail(false);                    }                } else {  // 没有读权限                    ToastUtil.show(UiUtil.getString(R.string.mine_without_read_permission));                }            }        });        ...    }    ...             /**     * 解密文件胜利     */    @Override    public void decryptPwdSuccess() {        if (inputPwdDialog != null && inputPwdDialog.isShowing()) {            inputPwdDialog.dismiss();        }        if (mFolderPwd == null) {            mFolderPwd = new FolderPassword(Constant.USER_ID, mFileBean.getPath(), filePwd, Constant.scope_token, TimeUtil.getCurrentTimeMillis());            mPresenter.insertFolderPwd(mFolderPwd);        } else {            updateFolderPwd();        }        toFolderDetail(true);    }    /**     * 更新文件夹明码     */    private void updateFolderPwd(){        mFolderPwd.setPassword(filePwd);        mFolderPwd.setModifyTime(TimeUtil.getCurrentTimeMillis());        mPresenter.updateFolderPwd(mFolderPwd);    }    /**     * 解密文件失败     *     * @param errorCode     * @param msg     */    @Override    public void decryptPwdFail(int errorCode, String msg) {        if (errorCode == ErrorConstant.PWD_ERROR) { // 文件夹明码谬误            if (inputPwdDialog != null && !inputPwdDialog.isShowing()) {                filePwd = "";                updateFolderPwd();                inputPwdDialog.show(this);            }        }    }     /**     * 获取明码胜利     *     * @param folderPassword     */    @Override    public void getFolderPwdByScopeTokenAndPathSuccess(FolderPassword folderPassword) {        LogUtil.e("查问文件夹明码胜利");        if (folderPassword != null) {            filePwd = folderPassword.getPassword();            long modifyTime = folderPassword.getModifyTime();            long distinct = TimeUtil.getCurrentTimeMillis() - modifyTime;            mFolderPwd = folderPassword;            if (TimeUtil.over72hour(distinct) || TextUtils.isEmpty(filePwd)) {  // 超过72小时                showInputPwdDialog();            } else {                checkFilePwd();            }        } else {            showInputPwdDialog();        }    }    /**     * 获取明码失败     */    @Override    public void getFolderPwdByScopeTokenAndPathFail() {        LogUtil.e("查问文件夹明码失败");        showInputPwdDialog();    }}/** * 文件的presenter层 */public class HomePresenter extends BasePresenter<HomeModel, HomeContract.View> implements HomeContract.Presenter {    ...    /**     * 解密文件夹     * @param scopeToken     * @param path     * @param checkPwdRequest     */    @Override    public void decryptFile(String scopeToken, String path, CheckPwdRequest checkPwdRequest) {        executeObservable(mModel.decryptFile(scopeToken, path, checkPwdRequest), new RequestDataCallback<Object>(false) {            @Override            public void onSuccess(Object response) {                super.onSuccess(response);                if (mView!=null){                    mView.decryptPwdSuccess();                }            }            @Override            public void onFailed(int errorCode, String errorMessage) {                super.onFailed(errorCode, errorMessage);                if (mView!=null){                    mView.decryptPwdFail(errorCode, errorMessage);                }            }        });    }    /**     * 获取本地保留的文件夹明码     * @param scopeToken     * @param path     */    @Override    public void getFolderPwdByScopeTokenAndPath(String scopeToken, String path) {        executeDBObservable(mModel.getFolderPwdByScopeTokenAndPath(scopeToken, path), new RequestDataCallback<FolderPassword>() {            @Override            public void onSuccess(FolderPassword response) {                super.onSuccess(response);                if (mView!=null){                    mView.getFolderPwdByScopeTokenAndPathSuccess(response);                }            }            @Override            public void onFailed() {                super.onFailed();                if (mView!=null){                    mView.getFolderPwdByScopeTokenAndPathFail();                }            }        });    }    /**     * 插入文件夹明码     * @param folderPassword     */    @Override    public void insertFolderPwd(FolderPassword folderPassword) {        executeDBObservable(mModel.insertFolderPwd(folderPassword), new RequestDataCallback<Boolean>() {            @Override            public void onSuccess(Boolean response) {                super.onSuccess(response);                if (mView!=null){                    if (response) {                        mView.insertFolderPwdSuccess(true);                    }else {                        mView.insertFolderFail();                    }                }            }            @Override            public void onFailed() {                super.onFailed();                if (mView!=null){                    mView.insertFolderFail();                }            }        });                ...        /**        * 校验文件夹明码是否正确        */        private void checkFilePwd() {            if (mFileBean != null) {                if (TextUtils.isEmpty(filePwd)){ // 如果明码为空,则输出                    inputPwdDialog.show(this);                }else { // 明码不为空,校验明码                    CheckPwdRequest checkPwdRequest = new CheckPwdRequest(filePwd);                    mPresenter.decryptFile(Constant.scope_token, mFileBean.getPath(), checkPwdRequest);                }            }        }    }    /**     * 批改文件夹明码     * @param folderPassword     */    @Override    public void updateFolderPwd(FolderPassword folderPassword) {        executeDBObservable(mModel.updateFolderPwd(folderPassword), new RequestDataCallback<Boolean>() {            @Override            public void onSuccess(Boolean response) {                super.onSuccess(response);                if (mView!=null) {                    if (response) {                        mView.updateFolderPwdSuccess();                    } else {                        mView.updateFolderPwdFail();                    }                }            }            @Override            public void onFailed() {                super.onFailed();                if (mView!=null){                    mView.updateFolderPwdFail();                }            }        });    }}

3) 数据库

智汀云盘存储文件夹明码相干信息的形式是应用Android本地数据库SqLite,应用的数据库框架是Greendao(greendao的应用,请参照官网文档,这里不再赘述greendao的应用),在查找文件夹明码时是通过文件夹的path和凭证查找的。上面是文件夹明码相干信息表的设计。

表名形容
id主键id
userId用户id
path文件夹门路
password文件夹明码
scopeToken凭证
modifyTime创立/批改工夫

以下是文件夹明码相干信息表的model类:

@Entitypublic class FolderPassword {    @Id(autoincrement = true)    private Long id;  // 主键id    private int userId;  // 用户id    private String path;  // 文件夹门路    private String password; // 文件夹明码    private String scopeToken;  // scopeToken    private Long modifyTime;  // 创立/批改工夫    ...        }