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

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

以下是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用户界面之按钮(Button)教程实例汇
  2. android ndk编译x264开源(用于android的ffmpeg中进行软编码)
  3. Android之应用程序基础
  4. Android使用Retrofit进行网络请求
  5. haproxy根据客户端浏览器进行跳转
  6. android用户界面-组件Widget-地图视图MapView
  7. android用户界面-组件Widget-画廊视图Gallery
  8. Android(安卓)View的介绍和使用
  9. Android(安卓)中文 API (27) —— SeekBar.OnSeekBarChangeListene

随机推荐

  1. Android(安卓)多个Activity之间的跳转 超
  2. 使用Android Studio查看Android 5.x源码
  3. [Android] Eclipse Android中设置模拟器
  4. android-xml布局属性 - 随心
  5. android之四大组件之一-Activity(三)
  6. Android模拟器及编译环境安装新手入门-3
  7. Jni/C for android 技术总揽
  8. 英特尔® Android* USB 驱动程序安装说明
  9. android studio创建模拟器报错解决 emula
  10. 【Android】高效ListView