Android7.0 LockSettingsService——StrongAuth机制介绍

Android6.0之后支持了指纹解锁,但是指纹本身的安全性是不如密码的,所以Android系统加入了StrongAuth机制,要求用户在某些情况下必须用密码解锁(例如手机重启后),之后才能用指纹解锁。

StrongAuth的相关定义

锁屏密码安全涉及到两个比较重要的类,LockPatternUtils和LockSettingsService,StrongAuth的相关常量定义和接口也被定义在这两个类里面,此外,还有一个专门的类LockSettingsStrongAuth.java用于处理一些核心事件
LockPatternUtils.java中定义了一个静态内部类StrongAuthTracker,里面定义了一些非常重要的常量

        /**
         * Strong authentication is not required.
         */
        public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;

        /**
         * Strong authentication is required because the user has not authenticated since boot.
         */
        public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;

        /**
         * Strong authentication is required because a device admin has requested it.
         */
        public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;

        /**
         * Some authentication is required because the user has temporarily disabled trust.
         */
        public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;

        /**
         * Strong authentication is required because the user has been locked out after too many
         * attempts.
         */
        public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;

        /**
         * Strong auth flags that do not prevent fingerprint from being accepted as auth.
         *
         * If any other flags are set, fingerprint is disabled.
         */
        private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
                | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;

根据这些常量的定义,不难看到以下的几种情况是无法使用指纹解锁的

  • 系统重启 STRONG_AUTH_REQUIRED_AFTER_BOOT
  • 设备管理器锁定 STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW
  • 错误次数过多 STRONG_AUTH_REQUIRED_AFTER_LOCKOUT

除此之外,其他情况下都是可以使用指纹解锁的
同时我们也可以发现,这些常量是16进制的int类型,会和ALLOWING_FINGERPRINT 进行位运算来判断当前是否能使用指纹解锁,这一点从StrongAuthTracker的对外接口就可以看出

        /**
         * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
         * current strong authentication requirements.
         */
        public boolean isFingerprintAllowedForUser(int userId) {
            return (getStrongAuthForUser(userId) & ~ALLOWING_FINGERPRINT) == 0;
        }

锁屏继承了这个类并加以扩展,用来判断当前系统是否允许指纹解锁

    public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
        public StrongAuthTracker(Context context) {
            super(context);
        }

        public boolean isUnlockingWithFingerprintAllowed() {
            int userId = getCurrentUser();
            return isFingerprintAllowedForUser(userId);
        }

        public boolean hasUserAuthenticatedSinceBoot() {
            int userId = getCurrentUser();
            return (getStrongAuthForUser(userId)
                    & STRONG_AUTH_REQUIRED_AFTER_BOOT) == 0;
        }

        @Override
        public void onStrongAuthRequiredChanged(int userId) {
            notifyStrongAuthStateChanged(userId);
        }
    }

StrongAuth的作用机制

前面说了LockSettingsStrongAuth.java是符合核心的处理逻辑,开机后会启动system server,LockSettingsService会实例化一个LockSettingsStrongAuth对象,调用其构造函数,根据系统设置的默认值来设置对应的flag

    public LockSettingsStrongAuth(Context context) {
        mDefaultStrongAuthFlags = StrongAuthTracker.getDefaultFlags(context);
    }
        public static @StrongAuthFlags int getDefaultFlags(Context context) {
            boolean strongAuthRequired = context.getResources().getBoolean(
                    com.android.internal.R.bool.config_strongAuthRequiredOnBoot);
            return strongAuthRequired ? STRONG_AUTH_REQUIRED_AFTER_BOOT : STRONG_AUTH_NOT_REQUIRED;
        }

完成初始化之后,锁屏也会建立起和LockSettingsService的联系,锁屏继承了静态类StrongAuthTracker,在这里面查询当前是否能够指纹解锁。

用户成功使用密码解锁之后会调用到LockSettingsStrongAuth的reportUnlock方法,这里面会重新设置flag

    public void reportUnlock(int userId) {
        requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
    }

最后来到这个函数

     private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) {
        int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags);
        int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED
                ? STRONG_AUTH_NOT_REQUIRED
                : (oldValue | strongAuthReason);
        if (oldValue != newValue) {
            mStrongAuthForUser.put(userId, newValue);
            notifyStrongAuthTrackers(newValue, userId);
        }
    }

当新旧的值不一样的时候就会通过notifyStrongAuthTrackers来通知各个继承了静态类StrongAuthTracker的类

        /**
         * Called when the strong authentication requirements for {@param userId} changed.
         */
        public void onStrongAuthRequiredChanged(int userId) {
        }

其他的情况也是一样的,最终都会调到handleRequireStrongAuthOneUser来改变当前的flag

8.0的新变化

前面说了三种无法使用指纹解锁的情况,但是系统还有一种情况也是不能使用指纹解锁的,即StrongAuthTimeOut,长时间没有使用密码解锁,但是这个功能被集成在锁屏的KeyguardUpdateMonitor里面,没有在LockSettingsService直接体现,默认时间是三天

    public boolean isUnlockingWithFingerprintAllowed() {
        return mStrongAuthTracker.isUnlockingWithFingerprintAllowed()
                && !hasFingerprintUnlockTimedOut(sCurrentUser);
    }
    /**
     * Default and maximum timeout in milliseconds after which unlocking with weak auth times out,
     * i.e. the user has to use a strong authentication method like password, PIN or pattern.
     *
     * @hide
     */
    public static final long DEFAULT_STRONG_AUTH_TIMEOUT_MS = 72 * 60 * 60 * 1000; // 72h

8.0之后这部分代码转移到了StrongAuthTracker中,也是出于安全和封装性的考虑,具体代码就不贴了,有兴趣可以查看8.0的源码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,649评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,039评论 25 707
  • 时间不知不觉中就已经过去了很久。曾经年少轻狂,暗自许下豪言壮语。憧憬着迷一样的未来。转过头来浑浑噩噩的度过...
    陈先生的腹肌阅读 550评论 0 0
  • 一段时间没有写东西了,最近放暑假背着电脑带着儿子回了老家。也当是让自己换个环境整理下思绪。 01 今年夏天最火的电...
    萧小月阅读 1,031评论 4 4
  • 素材来源:《TED演讲的秘密—18分钟改变世界》,杰瑞米·多诺万(美) 从小到大,我都不喜欢站在众人面前说话,那会...
    墨霜阅读 364评论 0 1