Android 在应用中使用用户凭证(PIN码、密码)

在Android开发过程需要使用到用户凭证来验证用户身份,验证成功用户才能继续操作。需要注意的是:minSdkVersion 必须大于或等于23,否则APP会报错。
先上效果图(在30s内不操作,点击确认按钮需要进行身份验证):
Android 在应用中使用用户凭证(PIN码、密码)_第1张图片
Android 在应用中使用用户凭证(PIN码、密码)_第2张图片以下是activity代码

import android.app.Activity;import android.app.KeyguardManager;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.security.keystore.KeyGenParameterSpec;import android.security.keystore.KeyPermanentlyInvalidatedException;import android.security.keystore.KeyProperties;import android.security.keystore.UserNotAuthenticatedException;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import java.io.IOException;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.UnrecoverableKeyException;import java.security.cert.CertificateException;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKey;public class CertificateActivity extends Activity{    /** Alias for our key in the Android Key Store. */    private static final String KEY_NAME = "my_key";    private static final byte[] SECRET_BYTE_ARRAY = new byte[] {1, 2, 3, 4, 5, 6};    private static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;    /**     * 如果用户在最近的几秒钟内解锁了设备,     *它可以视为身份验证者。     */    private static final int AUTHENTICATION_DURATION_SECONDS = 30;    private KeyguardManager mKeyguardManager;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_certificate);        mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);        Button purchaseButton = (Button) findViewById(R.id.purchase_button);        if (!mKeyguardManager.isKeyguardSecure()) {            // Show a message that the user hasn't set up a lock screen.            Toast.makeText(this,                    "没有设置设备锁定密码。\n"                            + "请去'设置 -> 安全 -> 屏幕锁定' 进行屏幕锁定设置!",                    Toast.LENGTH_LONG).show();            purchaseButton.setEnabled(false);            return;        }        createKey();        findViewById(R.id.purchase_button).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                // Test to encrypt something. It might fail if the timeout expired (30s).                tryEncrypt();            }        });    }    /**     * 尝试使用{@link #createKey}中生成的密钥加密某些数据     *仅在用户刚刚通过设备凭据进行身份验证时才有效。     */    private boolean tryEncrypt() {        try {            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");            keyStore.load(null);            SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_NAME, null);            Cipher cipher = Cipher.getInstance(                    KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/"                            + KeyProperties.ENCRYPTION_PADDING_PKCS7);            // Try encrypting something, it will only work if the user authenticated within            // the last AUTHENTICATION_DURATION_SECONDS seconds.            cipher.init(Cipher.ENCRYPT_MODE, secretKey);            cipher.doFinal(SECRET_BYTE_ARRAY);            // If the user has recently authenticated, you will reach here.            showAlreadyAuthenticated();            return true;        } catch (UserNotAuthenticatedException e) {            // User is not authenticated, let's authenticate with device credentials.            showAuthenticationScreen();            return false;        } catch (KeyPermanentlyInvalidatedException e) {            // This happens if the lock screen has been disabled or reset after the key was            // generated after the key was generated.            Toast.makeText(this, "密钥在创建后失效,\n"                            + e.getMessage(),                    Toast.LENGTH_LONG).show();            return false;        } catch (BadPaddingException | IllegalBlockSizeException | KeyStoreException |                CertificateException | UnrecoverableKeyException | IOException                | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {            throw new RuntimeException(e);        }    }    /**     * 在Android密钥存储区中创建对称密钥,该密钥只​​能在用户具有     *在最近X秒钟内使用设备凭据进行身份验证。     */    private void createKey() {        // Generate a key to decrypt payment credentials, tokens, etc.        // This will most likely be a registration step for the user when they are setting up your app.        try {            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");            keyStore.load(null);            KeyGenerator keyGenerator = KeyGenerator.getInstance(                    KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");            // Set the alias of the entry in Android KeyStore where the key will appear            // and the constrains (purposes) in the constructor of the Builder            keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,                    KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)                    .setBlockModes(KeyProperties.BLOCK_MODE_CBC)                    .setUserAuthenticationRequired(true)                    // Require that the user has unlocked in the last 30 seconds                    .setUserAuthenticationValidityDurationSeconds(AUTHENTICATION_DURATION_SECONDS)                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)                    .build());            keyGenerator.generateKey();        } catch (NoSuchAlgorithmException | NoSuchProviderException                | InvalidAlgorithmParameterException | KeyStoreException                | CertificateException | IOException e) {            throw new RuntimeException("Failed to create a symmetric key", e);        }    }    private void showAuthenticationScreen() {        // Create the Confirm Credentials screen. You can customize the title and description. Or        // we will provide a generic one for you if you leave it null        Intent intent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null);        if (intent != null) {            startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);        }    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {            // Challenge completed, proceed with using cipher            if (resultCode == RESULT_OK) {                if (tryEncrypt()) {                    showPurchaseConfirmation();                }            } else {                // The user canceled or didn’t complete the lock screen                // operation. Go to error/cancellation flow.                Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show();            }        }    }    private void showPurchaseConfirmation() {        findViewById(R.id.confirmation_message).setVisibility(View.VISIBLE);        findViewById(R.id.purchase_button).setEnabled(false);    }    private void showAlreadyAuthenticated() {        TextView textView = (TextView) findViewById(                R.id.already_has_valid_device_credential_message);        textView.setVisibility(View.VISIBLE);        findViewById(R.id.purchase_button).setEnabled(false);    }}

这是xml代码

<?xml version="1.0" encoding="utf-8"?>                    

更多相关文章

  1. android multi user中MTP 多用户的处理
  2. RMS认为Android没有尊重用户自由
  3. Android 系统用户态启动过程
  4. 判断用户使用的是 Android 手机还是平板
  5. Android用户定位Google Map显示地图
  6. android 布局随笔----用户登录界面
  7. Android官方技术文档翻译——Gradle 插件用户指南(7)
  8. Android模拟用户点击的实现方法
  9. Android通过共享用户ID来实现多Activity进程共享

随机推荐

  1. Python与家国天下
  2. oss上传文件阿里云(js版本)
  3. JQuery框架的使用
  4. 小白也能学会装“win10系统”,轻松撩妹
  5. 介绍几款 Python 类型检查工具
  6. Python猫荐书之六:文也深度学习,理也深度学
  7. 视频当道的时代,这些珍藏的优质 Python 播
  8. MySQL 8 OCP(1Z0-908)认证考试题库原题(第
  9. 如何给列表降维?sum()函数的妙用
  10. Python进阶:如何将字符串常量转为变量?