问题提出
项目代码最近进行梆梆应用安全检测,被曝出存在剪切板敏感信息泄漏的中风险漏洞,需要修复。
问题分析
android系统中,EditText继承自TextView,长按或双击文本时,会弹出操作菜单,可以进行全选、复制、剪切、粘贴、分享等操作。剪贴板上的数据可在不同的应用之间共享。如果被操作的文本涉及账号、手机号、交易信息等用户隐私数据,就会存在严重的安全漏洞。
分析EditText和TextView源码,发现是TextView里设置了ActionMode.Callback对象,入口方法是setCustomSelectionActionModeCallback()。
解决方案
自定义控件继承自EditText,设置自定义的ActionMode.Callback对象,屏蔽部分菜单选项。话不多说,解决前后的效果图如下:
上代码:
package com.bg.blogcodeproject.widget.edittext;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.widget.AppCompatEditText;
/**
* @Desc:屏蔽复制剪切分享菜单的EditText
* @Author:bg
* @Time:2/28/22 9:55 AM
* 扩展:换做TextView,原理相同,不再另论
*/
public class NoCopyCutShareEditText extends AppCompatEditText {
public NoCopyCutShareEditText(Context context) {
this(context, null);
}
public NoCopyCutShareEditText(Context context, AttributeSet attrs) {
this(context, attrs, androidx.appcompat.R.attr.editTextStyle);
}
public NoCopyCutShareEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setCustomActionModeCallback();
}
/**
* 设置文本选择Action的回调对象
*/
private void setCustomActionModeCallback() {
super.setCustomSelectionActionModeCallback(new NoCopyCutShareAction());
}
private static class NoCopyCutShareAction implements ActionMode.Callback {
/**
* Called when action mode is first created. The menu supplied will be used to
* generate action buttons for the action mode.
*
* @param mode ActionMode being created
* @param menu Menu used to populate action buttons
* @return true if the action mode should be created, false if entering this
* mode should be aborted.
*/
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// 在菜单创建阶段删除复制、剪切、分享菜单项
menu.removeItem(android.R.id.copy);
menu.removeItem(android.R.id.cut);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
menu.removeItem(android.R.id.shareText);
}
return true;
}
/**
* Called to refresh an action mode's action menu whenever it is invalidated.
*
* @param mode ActionMode being prepared
* @param menu Menu used to populate action buttons
* @return true if the menu or action mode was updated, false otherwise.
*/
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
/**
* Called to report a user click on an action button.
*
* @param mode The current ActionMode
* @param item The item that was clicked
* @return true if this callback handled the event, false if the standard MenuItem
* invocation should continue.
*/
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
/**
* Called when an action mode is about to be exited and destroyed.
*
* @param mode The current ActionMode being destroyed
*/
@Override
public void onDestroyActionMode(ActionMode mode) {
}
}
/**
* 文本选择菜单项选中执行回调
*
* @return false对当前菜单项不执行
*/
@Override
public boolean onTextContextMenuItem(int id) {
if (id == android.R.id.copy || id == android.R.id.cut) {
return false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && id == android.R.id.shareText) {
return false;
}
return super.onTextContextMenuItem(id);
}
}
网友评论