智汀云盘-开发指南android端:文件夹解密逻辑

1. 文件夹解密说明

只有加密的文件夹才需要解密,同一用户在查看同一加密文件夹或者是里面的文件/文件夹,每次成功校验密码后,再次查看同一加密文件夹或里面的文件/文件夹,不用输入密码,72个小时后查看才需要输入密码;(除非有修改密码,如有修改密码,则需要重新输入,修改后第一次成功验证密码后再开始计算72小时)。

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

2. 文件夹解密过程

1) 解密过程说明

我们在访问加密的文件时:

先去根据scopeToken和path去本地数据库(sqlite)查找该文件先前是否有保存解密密码
如果存在的话,则会校验该条数据是否超过72小时,在没有超过72小时的情况下就拿这条数据的密码访问接口Get:/api/plugin/wangpan/folders/:path 校验密码是否正确:
正确的话进入文件夹详情,并更新该文件夹本地保存的密码和修改时间;
错误需要重新输入密码并访问接口校验该密码是否正确;
校验数据是超过72小时的情况下,需要输入密码并访问接口校验该密码是否正确:
在正确的情况下更新该文件夹本地保存的密码和修改时间,并插入该文件的密码缓存信息到数据库;
否则提示用户密码错误,重新输入;

2) 主要代码实现

/**
 * 文件
 */
public class HomeFragment extends BaseMVPDBFragment 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 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(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() {
            @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() {
            @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() {
            @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类:

@Entity
public 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;  // 创建/修改时间
    ...
        
}

你可能感兴趣的:(android)