Android 剪切板敏感信息泄露漏洞解決:禁用EditText的複製粘貼功能

Android 中任何第三方軟件都可訪問剪切板內容,雖然高版本對剪切板做了訪問限制,但是還是需要照顧一下低版本的,解決方法就是要禁用EditText的複製粘貼功能,讓用戶不能向剪切板中放置內容。下邊就來說說具體實現吧。

1、自定義NoMenuEditText 繼承自AppCompatEditText

2、重寫isSuggestionsEnabled方法並返回false

     創建canPaste()方法並返回false。該方法是一個隱藏方法

3、實現ActionMode.Callback回調

 private class ActionModeCallbackInterceptor implements ActionMode.Callback {

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {
        }
    }

4、設置回調

      this.setLongClickable(false);
        //this.setTextIsSelectable(false);
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        //使用該方式基本可以實現禁用粘貼複製功能,6.0以上可用
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor());
        }

使用以上方式即可禁用掉EditText的複製粘貼功能,但是長按EditTeit控件中的文本時光標會有變化,並且該方式只能在6.0以上版本中使用。如果以上方式不能滿足你的需求,請看以下方式:

1、2、3步同上,修改第4步不再用 this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor())方法。

使用以下方式(反射)代替:

 this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                NoMenuEditText.this.clearFocus();
                return false;
            }
        });
@SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // setInsertionDisabled when user touches the view
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    private void setInsertionDisabled() {
        try {
            Field editorField = TextView.class.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editorObject = editorField.get(this);

            @SuppressLint("PrivateApi") Class editorClass = Class.forName("android.widget.Editor");
            Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
            mInsertionControllerEnabledField.setAccessible(true);
            mInsertionControllerEnabledField.set(editorObject, false);
        } catch (Exception ignored) {
        }
    }

使用這種方式即可解決第一種方式的版本兼容問題,並且長按EditText控件中的文本光標也不會有任何變化,完美解決剪切板敏感信息泄露問題。希望以上方案對你有所幫助。

伸手黨請看如下完整代碼(別忘了點個贊哦):

@SuppressLint("NewApi")
public class NoMenuEditText extends AppCompatEditText {
    private final Context context;

    /**
     * 該方法爲隱藏方法
     */
    boolean canPaste() {
        return false;
    }

    @Override
    public boolean isSuggestionsEnabled() {
        return false;
    }

    public NoMenuEditText(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public NoMenuEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    @SuppressLint("ClickableViewAccessibility")
    private void init() {
        this.setLongClickable(false);
        //this.setTextIsSelectable(false);
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        //使用該方式基本可以實現禁用粘貼複製功能,6.0以上可用
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//            this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor());
//        }
        this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                NoMenuEditText.this.clearFocus();
                return false;
            }
        });
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // setInsertionDisabled when user touches the view
            this.setInsertionDisabled();
        }
        return super.onTouchEvent(event);
    }

    private void setInsertionDisabled() {
        try {
            Field editorField = TextView.class.getDeclaredField("mEditor");
            editorField.setAccessible(true);
            Object editorObject = editorField.get(this);

            @SuppressLint("PrivateApi") Class editorClass = Class.forName("android.widget.Editor");
            Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
            mInsertionControllerEnabledField.setAccessible(true);
            mInsertionControllerEnabledField.set(editorObject, false);
        } catch (Exception ignored) {
        }
    }

    /**
     * Prevents the action bar (top horizontal bar with cut,copy,paste,etc.)
     * from appearing by intercepting the callback that would cause it to be
     * created,and returning false.
     */
    private class ActionModeCallbackInterceptor implements ActionMode.Callback {

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            return false;
        }

        public void onDestroyActionMode(ActionMode mode) {
        }
    }
}

參考:https://stackoverflow.com/questions/41673185/disable-edittext-context-menu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章