指紋識別

說明

指紋認證一般我們期望是這樣的:

  1. 指紋支付可以和手指綁定,比和微信支付一樣:開啟時輸入一個指紋,每次支付的時候只能用當(dāng)時綁定的指紋支付,這樣可以保證指紋安全。
  2. 如果上面的走不通的話,那就只能和招商銀行指紋登錄一樣:開啟指紋登錄時驗證指紋,驗證通過之后,以后每次登錄都可以通過驗證輸入的指紋是否是錄入系統(tǒng)中的任何一個指紋。 如果你開通指紋后,又在系統(tǒng)中錄入了新的指紋,下次用指紋登錄招商銀行的時候就會被提示指紋發(fā)生了變化。

我個人調(diào)研指紋認證方案主要是下面兩種:

  1. 使用微信開源Soter庫

這個方案的優(yōu)點就是穩(wěn),據(jù)說微信的指紋支付就是使用的這個方案,和國產(chǎn)設(shè)備廠商合作的.可以定位的具體的哪個手指,可以獲取到指紋Id. 不足之處就是不支持華為手機和國外部分廠商(沒有和Soter合作的). 雖然微信客戶端是支持華為指紋的.但是這個框架是暫時不支持的.(很久之前就說要支持,截至目前仍未支持)

  1. 使用系統(tǒng)官方Api
  • 優(yōu)點:支持所有android 6.0以上的指紋設(shè)備(招商銀行80%可能性使用的就是這個方案)

  • 缺點:

    1. 不能獲取指紋Id,不能和手指綁定,同能通過判斷指紋庫是否變化保證安全
    2. 需要針對android 6.0 和android 9.0 適配 : android 9.0 以下需要自己實現(xiàn)指紋識別彈窗樣式 ,但是android 9.0 開始統(tǒng)一由系統(tǒng)彈窗實現(xiàn)(不同廠商可能還不一樣)

    綜合考慮我們選擇使用系統(tǒng)官方Api實現(xiàn)第二種方案,只支持所有android 6.0 以上的指紋設(shè)備

效果演示

  1. android M
  • 指紋識別成功


    m-success.gif
  • 指紋驗證失敗


    m-fail.gif
  • 指紋數(shù)據(jù)發(fā)生了改變


    m-change.gif
  1. android P
  • 指紋識別成功


    p-success.gif
  • 指紋驗證失敗


    p-fail.gif
  • 指紋數(shù)據(jù)發(fā)生了改變


    p-change.gif

快速集成

在項目下的build.gradle文件中

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

在app下的build.gradle文件中

implementation 'com.github.LambdaXiao:BiometricManager:v1.1.0'

具體使用如下:

findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    switch (FingerManager.checkSupport(MainActivity.this)) {
                        case DEVICE_UNSUPPORTED:
                            showToast("您的設(shè)備不支持指紋");
                            break;
                        case SUPPORT_WITHOUT_DATA:
                            showToast("請在系統(tǒng)錄入指紋后再驗證");
                            break;
                        case SUPPORT:
                            FingerManager.build().setApplication(getApplication())
                                    .setTitle("指紋驗證")
                                    .setDes("請按下指紋")
                                    .setNegativeText("取消")
//                                    .setFingerDialogApi23(new MyFingerDialog())//如果你需要自定義android P 以下系統(tǒng)彈窗就設(shè)置,注意需要繼承BaseFingerDialog,不設(shè)置會使用默認彈窗
                                    .setFingerCallback(new SimpleFingerCallback() {
                                        @Override
                                        public void onSucceed() {
                                            showToast("驗證成功");
                                        }

                                        @Override
                                        public void onFailed() {
                                            showToast("指紋無法識別");
                                        }

                                        @Override
                                        public void onChange() {
                                            showToast("指紋數(shù)據(jù)發(fā)生了變化");
                                        }
                                    })
                                    .create()
                                    .startListener(MainActivity.this);
                            break;
                        default:
                    }
                }
            }
        });

支持功能

  1. 檢查設(shè)備是否支持指紋:分為三種支持,分別是(1)設(shè)備沒有指紋識別器 (2)設(shè)備有指紋識別器但是沒有指紋數(shù)據(jù)(3)設(shè)備有識別器并且有指紋數(shù)據(jù),可以進行指紋驗證
  2. 監(jiān)聽相應(yīng)手機指紋庫數(shù)據(jù)發(fā)生變化的情況
  3. 指紋數(shù)據(jù)發(fā)生變化后可以調(diào)用updateFingerData()方法更新同步變化
  4. 能夠?qū)θ∠讣y識別和指紋識別失敗分別進行處理
  5. 需要適配android版本,在android版本大于6.0 小于9.0 的情況下要自己實現(xiàn)指紋識別彈窗。在android P上要使用最新Api調(diào)用指紋識別統(tǒng)一彈窗

如何監(jiān)聽指紋數(shù)據(jù)變化

  1. 創(chuàng)建SecretKey對當(dāng)前指紋數(shù)據(jù)加密,如果在創(chuàng)建SecretKey后添加新指紋,則會在Cipher初始化時引發(fā)KeyPermanentlyInvalidatedException.通過這個異常我們可以知道指紋數(shù)據(jù)是否發(fā)生變化
/**
     * @des 初始化Cipher ,根據(jù)KeyPermanentlyInvalidatedExceptiony異常判斷指紋庫是否發(fā)生了變化
     *
     */
    public boolean initCipher(Cipher cipher) {
        try {
            keyStore.load(null);
            SecretKey key = (SecretKey) keyStore.getKey(KEYSTORE_ALIAS, null);
            if (cipher == null) {
                cipher = createCipher();
            }
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return false;
        } catch (KeyPermanentlyInvalidatedException e) {
            //指紋庫是否發(fā)生了變化,這里會拋KeyPermanentlyInvalidatedException
            return true;
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException
                | NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("Failed to init Cipher", e);

        }
    }
  1. 唯一例外的是三星手機不會拋出KeyPermanentlyInvalidatedException這個異常,經(jīng)過反復(fù)測試,發(fā)現(xiàn)三星手機可以根據(jù)識別成功后的回調(diào)方法中檢測cipher.doFinal(SECRET_MESSAGE.getBytes())這里的異常判斷指紋數(shù)據(jù)是否發(fā)生變化
                    @Override
                    public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
                        super.onAuthenticationSucceeded(result);
                        Cipher cipher = result.getCryptoObject().getCipher();
                        if (cipher != null) {
                            try {
                                /*
                                 * 用于檢測三星手機指紋庫變化,
                                 * 三星手機指紋庫發(fā)生變化后前面的initCipher檢測不到KeyPermanentlyInvalidatedException
                                 * 但是cipher.doFinal(SECRET_MESSAGE.getBytes())會拋出異常
                                 * 因此以此監(jiān)聽三星手機的指紋庫變化
                                 */
                              
                                cipher.doFinal(SECRET_MESSAGE.getBytes());
                                
                                cancel.cancel();
                                mFingerDialog.onSucceed();
                                mFingerCallback.onSucceed();
                            } catch (Exception e) {
                                e.printStackTrace();
                                mFingerCallback.onChange();
                            }
                        }

自定義android 9.0以下彈窗

如果你想自定義android M 的指紋識別彈窗,很簡單,你只需要:

  1. 繼承BaseFingerDialog類
  2. 在onCreateView中初始化你自己的布局
  3. 實現(xiàn)onSucceed()、onFailed()、onHelp()、onError()四個回調(diào)就好了,這四個回調(diào)建議只做UI相關(guān)操作,邏輯操作已經(jīng)在外部提供了回調(diào)接口。
    1. onSucceed :指紋識別成功,可以直接關(guān)閉彈窗
    2. onFailed : 當(dāng)識別的手指沒有注冊時回調(diào),但是可以繼續(xù)驗證
    3. onHelp : 指紋識別不對,會提示,手指不要大范圍移動等信息,可以繼續(xù)驗證
    4. onError :指紋識別徹底失敗,不能繼續(xù)驗證
    5. 一個指紋識別事件序列是這樣的: 開始識別 ---> (onHelp / onFaild) (0個或多個) ---> onSucceed / onError

調(diào)起指紋識別得時候,將自定義的彈窗設(shè)置進去,代碼如下,如果你不設(shè)置自定義彈窗會使用默認的android M 彈窗

FingerManager.build().setApplication(getApplication())
                .setTitle("指紋驗證")
                .setDes("請按下指紋")
                .setNegativeText("取消")
                .setFingerDialogApi23(new MyFingerDialog())
                .setFingerCheckCallback()

最后貼出github鏈接:https://github.com/LambdaXiao/BiometricManager

參考鏈接

https://github.com/googlearchive/android-FingerprintDialog
https://android.ctolib.com/mengcuiguang-FingerDemo.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容