美文网首页
Android7.0 LockSettingsService——

Android7.0 LockSettingsService——

作者: Lonelyyy | 来源:发表于2017-12-26 23:09 被阅读0次

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的源码

相关文章

网友评论

      本文标题:Android7.0 LockSettingsService——

      本文链接:https://www.haomeiwen.com/subject/ceargxtx.html