項(xiàng)目需求討論- 讓APP知道是用哪個(gè)指紋來支付和解鎖

以前我寫過相關(guān)的指紋解鎖的文章:

傳送門: 項(xiàng)目需求討論-APP手勢(shì)解鎖及指紋解鎖
那時(shí)候做的APP解鎖是調(diào)用系統(tǒng)的指紋解鎖功能,同時(shí),進(jìn)行指紋驗(yàn)證的時(shí)候,只要是手機(jī)中錄制過的指紋,然后在指紋驗(yàn)證過程中就會(huì)認(rèn)為認(rèn)證成功。但僅僅這樣,很難滿足一些驗(yàn)證要求比較高的APP,比如支付類型的APP。不然我不是本人。我是女朋友啊,或者誰,我在你手機(jī)里有個(gè)指紋,為了方便解鎖屏。又或者,一般朋友玩你的手機(jī),問你鎖屏密碼,你也會(huì)說出來,畢竟想想是鎖屏密碼,然后去設(shè)置里面添加指紋也只需要鎖屏密碼,這時(shí)候那個(gè)朋友偷偷去錄了個(gè)自己的指紋,豈不是你的指紋驗(yàn)證就形同虛設(shè)了。豈不是也就馬上掌握你的支付賬戶了。

我來說下支付寶的指紋相關(guān)方式:

前提:我手機(jī)上有左右大拇指的指紋已經(jīng)錄制好了

  1. 你到支付寶的設(shè)置界面,開啟指紋支付功能,這時(shí)候會(huì)跳出彈框,讓你驗(yàn)證指紋:



    這時(shí)候如果我用右邊的指紋來進(jìn)行驗(yàn)證,這時(shí)候指紋驗(yàn)證通過了。就讓你進(jìn)行密碼驗(yàn)證,證明你這個(gè)指紋的人同時(shí)也是知道密碼的。

你輸入完正確的密碼后,算是正式的綁定上了。就代表你這個(gè)指紋具有相應(yīng)的支付功能。

  1. 到了支付界面,我們用右手拇指去支付,OK,肯定是沒問題的,如果這時(shí)候我故意用左手的拇指去支付,會(huì)出錯(cuò):

那就說明,我們的指紋具有一個(gè)id值,能讓服務(wù)器那邊知道當(dāng)前這個(gè)指紋是不是我們綁定的指紋。

順便提一句,ios我試了下,當(dāng)你在手機(jī)添加了一個(gè)指紋后,他就會(huì)不讓你進(jìn)行支付,比如我們?cè)瓉硎怯沂帜粗钢Ц兜模?dāng)你添加一個(gè)新的指紋后,就算你用右手指紋去付錢,也不行,所以這里我認(rèn)為ios是監(jiān)聽了系統(tǒng)指紋的變化情況,比如新增了指紋。而不是判斷到底具體是哪一個(gè)指紋


這個(gè)但是我們知道我們指紋驗(yàn)證通過的都是系統(tǒng)底層的API,我們的API最后返回驗(yàn)證結(jié)果給我們的內(nèi)容中,是否帶有相關(guān)的參數(shù),我們可以繼續(xù)往下看:

在我的文章 項(xiàng)目需求討論-APP手勢(shì)解鎖及指紋解鎖 我提過,最后指紋驗(yàn)證通過是回調(diào):

@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
    .....
    .....
    .....
}

我們可以看到指紋驗(yàn)證通過后的回調(diào)方法參數(shù)是FingerprintManager.AuthenticationResult,我們?cè)賮砜聪逻@個(gè)類

public static class AuthenticationResult {
    private Fingerprint mFingerprint;
    private CryptoObject mCryptoObject;

    /**
     * Authentication result
     *
     * @param crypto the crypto object
     * @param fingerprint the recognized fingerprint data, if allowed.
     * @hide
     */
    public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
        mCryptoObject = crypto;
        mFingerprint = fingerprint;
    }

    /**
     * Obtain the crypto object associated with this transaction
     * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
     *     CancellationSignal, int, AuthenticationCallback, Handler)}.
     */
    public CryptoObject getCryptoObject() { return mCryptoObject; }

    /**
     * Obtain the Fingerprint associated with this operation. Applications are strongly
     * discouraged from associating specific fingers with specific applications or operations.
     *
     * @hide
     */
    public Fingerprint getFingerprint() { return mFingerprint; }
};

這個(gè)類很簡單,里面就二個(gè)屬性值:FingerprintCryptoObject,我們?cè)賮砜?code>Fingerprint類的內(nèi)容:

/**
 * Container for fingerprint metadata.
 * @hide
 */
public final class Fingerprint implements Parcelable {
    private CharSequence mName;
    private int mGroupId;
    private int mFingerId;
    private long mDeviceId; // physical device this is associated with
    
    ....
    ....
    ....

}

沒錯(cuò)。里面有mFingerId等參數(shù)。豈不是我們直接拿這個(gè)值不就行了??這么簡單???

答案當(dāng)然是No,因?yàn)槟慊仡^再看上面的AuthenticationResult類里面的getFingerprint()方法上面用@hide修飾了,而且我們的Fingerprint類上面也用@hide修飾了。

但是大家心里一定會(huì)想,那我不是用反射來調(diào)用getFingerprint()方法拿到Fingerprint對(duì)象,從而再來拿mFingerId不就好了。

比如我在這里寫上反射獲取:

@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
    mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
    mIcon.setImageResource(R.drawable.ic_fingerprint_success);
    mErrorTextView.setTextColor(
            mErrorTextView.getResources().getColor(R.color.success_color, null));
    mErrorTextView.setText(
            mErrorTextView.getResources().getString(R.string.fingerprint_success));
    mIcon.postDelayed(new Runnable() {
        @Override
        public void run() {
            mCallback.onAuthenticated();
        }
    }, SUCCESS_DELAY_MILLIS);

    //通過反射來獲取
    try {
       
        Method method1 = result.getClass().getMethod("getCryptoObject");
        Object cryptoObject = method1.invoke(result, new Object[]{});
        
        Method method2 = result.getClass().getMethod("getFingerprint");
        Object fingerPrint = method2.invoke(result, new Object[]{});
        
    } catch ( NoSuchMethodException e ) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

你會(huì)發(fā)現(xiàn)就算通過反射來拿Fingerprint對(duì)象,拿到的也是null。而我用同樣的代碼來拿CryotoObject對(duì)象就是有內(nèi)容的。

所以這里我們用反射也出現(xiàn)了問題,那我們自己普通程序員開發(fā)應(yīng)該怎么來處理呢。
(ps:StackOverflow上也有人提出相同的問題:Fingerprint為null,他是直接把a(bǔ)ndroid.jar包換了。換成了這里沒有@hide修飾了。這樣就可以直接在代碼里面使用,但是拿到的也是null。)


主角: Tencent/soter

TENCENT SOTER是騰訊于2015年開始制定的生物認(rèn)證平臺(tái)與標(biāo)準(zhǔn),通過與廠商合作,目前已經(jīng)在一百余款、數(shù)億部Android設(shè)備上得到支持,并且這個(gè)數(shù)字還在快速增長。

目前,TENCENT SOTER已經(jīng)在微信指紋支付、微信公眾號(hào)/小程序指紋授權(quán)接口等場景使用,并得到了驗(yàn)證。

接入TENCENT SOTER,你可以在不獲取用戶指紋圖案的前提下,在Android設(shè)備上實(shí)現(xiàn)可信的指紋認(rèn)證,獲得與微信指紋支付一致的安全快捷認(rèn)證體驗(yàn)。

為什么要用TENCENT SOTER:

這里可以對(duì)比下系統(tǒng)原生Android 6.0指紋接口和FIDO方案。

TENCENT SOTER Android Framework FIDO
安全性 高(前后臺(tái)支持,有產(chǎn)線生成一機(jī)一密根密鑰) 低(手機(jī)被root后易被破解,且無法準(zhǔn)確檢測(cè)root) 高(前后臺(tái)支持,有產(chǎn)線生成根密鑰)
接入成本 較低(前端極輕量級(jí)sdk,后臺(tái)無須集成sdk) 低(無需前后臺(tái)sdk) 高(部署復(fù)雜)
敏感業(yè)務(wù)可用 是(可獲取本機(jī)指紋索引) 否(無法獲取指紋在本機(jī)索引,有盜用風(fēng)險(xiǎn)) 是(可獲取本機(jī)指紋索引)
用戶隱私保護(hù) 好(不會(huì)獲取指紋圖案) 好(不會(huì)獲取指紋圖案) 好(不會(huì)獲取指紋圖案)
商業(yè)隱私保護(hù) 好(驗(yàn)證無須請(qǐng)求到中心服務(wù)) \ 較差(需要每一筆驗(yàn)證都請(qǐng)求到中心驗(yàn)證服務(wù)器)

當(dāng)然最主要的功能是:
同時(shí),對(duì)比與原生接口,也有兩個(gè)明顯優(yōu)勢(shì):
支持部分Android L(Android 5.0、5.1)機(jī)型指紋認(rèn)證
可以提供本次認(rèn)證在本機(jī)上的指紋索引以區(qū)分手指

更多請(qǐng)看:什么是TENCENT SOTER
SOTER支持的機(jī)型:SOTER 指紋支持機(jī)型


所以我們看到了。它可以提供本機(jī)上的指紋索引來區(qū)分手機(jī)。

我們使用github soter上面提供的Demo。我們可以運(yùn)行demo,這時(shí)候出現(xiàn)一些情況:

  1. 有些人運(yùn)行demo,可能會(huì)開啟指紋功能的時(shí)候會(huì)失敗,可能是你的機(jī)型不支持。我使用小米5不行,使用的OPPO A57就可以了。
  2. 大家可能看到華為上面一臺(tái)都沒有。在issue里面我們也看到了。騰訊正在和華為洽談,而且說了技術(shù)上面是沒有任何問題的。所以后續(xù)大家也可以不用擔(dān)心
  3. 最后你用指紋解鎖的時(shí)候,可以再回調(diào)函數(shù)中查看相關(guān)的log信息:
soterdemo: use fingerprint payment result: total: SoterCoreResult{errCode=0, errMsg=''}, extData: SoterSignatureResult{rawValue='I'm a demo challenge string', fid='3374914681109099800', counter=42, TEEName='QSEE', TEEVersion='4', FpName='fingerprint', FpVersion='1', cpuId='000000000006b0e13a925a082575ca3e', saltLen=20, jsonValue='{"raw":"I'm a demo challenge string","fid":"3374914681109099800","counter":42,"tee_n":"QSEE","tee_v":"4","fp_n":"fingerprint","fp_v":"1","cpu_id":"000000000006b0e13a925a082575ca3e","uid":"10107"}', signature='J7jNgKFc2TMExrx3dLJAiAFF25cwZvUhGWLQJPhhbHKsHTLi+/eAsJd7gmgAJnZsCQrHq2vnIeW8j0Rj81aRbF1Svv5tNRJt1Gyzewu9Lpa7E5rwTJ97otJPWv3b3nxyDicYQaEZbzqGSYeKga+tUutDlISzvFOLqrikX/OT0W5M0/szFIpkrEAJiMGYNqg451iijN3dM6pB9AXgs6qohz25sWbF6OEthvAO9hI9Ddsm5bn69Ct/3f4eaB3eb/Ljo/Hs8YK//UhkvXn4OcOsnsmHZ6P6jaNcC60iylxxLuPc2PwMd8dRPDKk8S0HEyjT7SpaQqIO2j7/hbi2by0QJg=='}, signature data is: SoterSignatureResult{rawValue='I'm a demo challenge string', fid='3374914681109099800', counter=42, TEEName='QSEE', TEEVersion='4', FpName='fingerprint', FpVersion='1', cpuId='000000000006b0e13a925a082575ca3e', saltLen=20, jsonValue='{"raw":"I'm a demo challenge string","fid":"3374914681109099800","counter":42,"tee_n":"QSEE","tee_v":"4","fp_n":"fingerprint","fp_v":"1","cpu_id":"000000000006b0e13a925a082575ca3e","uid":"10107"}', signature='J7jNgKFc2TMExrx3dLJAiAFF25cwZvUhGWLQJPhhbHKsHTLi+/eAsJd7gmgAJnZsCQrHq2vnIeW8j0Rj81aRbF1Svv5tNRJt1Gyzewu9Lpa7E5rwTJ97otJPWv3b3nxyDicYQaEZbzqGSYeKga+tUutDlISzvFOLqrikX/OT0W5M0/szFIpkrEAJiMGYNqg451iijN3dM6pB9AXgs6qohz25sWbF6OEthvAO9hI9Ddsm5bn69Ct/3f4eaB3eb/Ljo/Hs8YK//UhkvXn4OcOsnsmHZ6P6jaNcC60iylxxLuPc2PwMd8dRPDKk8S0HEyjT7SpaQqIO2j7/hbi2by0QJg=='}

其中比較重要的就是fid='3374914681109099800',不同的指紋,這個(gè)ID值是不同的。所以我們可以用來判斷了。


還是那句老話,可能我哪里講的不對(duì)。大家請(qǐng)下面留言。多回復(fù)多點(diǎn)贊。哈哈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,242評(píng)論 25 708
  • 好久沒寫文章了,最近也比較偷懶,今天繼續(xù)討論我實(shí)際開發(fā)中遇到的需求,那就是關(guān)于APP解鎖,大家都知道。現(xiàn)在越來越多...
    青蛙要fly閱讀 3,128評(píng)論 2 26
  • 有一個(gè)人從來沒有傾訴過自己的感情,從來沒有抱怨過生活的艱辛,她總是坐在窗前的木凳上默默地看著孩子們來,孩子們走。 ...
    迷糊香香閱讀 494評(píng)論 4 2
  • HTTP Live Streaming技術(shù)概覽:基本原理是將視頻文件或視頻流切分成小片(ts)并建立索引文件(m3...
    TrueMeaning閱讀 606評(píng)論 0 0
  • by:孤鳥差魚 嫌表面的太過膚淺 厚重的你看不明白 還愛評(píng)判 你還要我怎樣
    孤鳥差魚閱讀 212評(píng)論 0 2