Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách lưu mật khẩu trong WebView Android

Giới thiệu

Hướng dẫn này trình bày cách bật tính năng lưu mật khẩu (save password) cho Android WebView. Lưu ý quan trọng: Từ Android 8.0 (API 26), phương thức WebSettings.setSavePassword() đã bị deprecated và không còn hoạt động do chính sách bảo mật của Google.

Các bước thực hiện (Phương pháp cũ - Deprecated)

Bước 1: Tạo dự án mới

Tạo dự án Android Studio: File → New Project.

Bước 2: Layout activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Bước 3: MainActivity.java (Code cũ - KHÔNG HOẠT ĐỘNG TỪ API 26+)

package com.example.myapplication;

import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.app.ProgressDialog;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Đang tải dữ liệu...");
        progressDialog.setCancelable(false);

        WebView webView = findViewById(R.id.web_view);
        webView.requestFocus();
        
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        
        // DEPRECATED TỪ API 26 (Android 8.0) - KHÔNG CÒN HOẠT ĐỘNG
        // webSettings.setSavePassword(true);
        // webSettings.setSaveFormData(true); // Cũng deprecated
        
        webView.loadUrl("https://touch.facebook.com/");

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                if (newProgress < 100) {
                    progressDialog.show();
                }
                if (newProgress == 100) {
                    progressDialog.dismiss();
                }
            }
        });
    }
}

Bước 4: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                

Tại sao setSavePassword() bị deprecated?

Lý doGiải thích
Bảo mậtLưu mật khẩu plaintext trong WebView database không an toàn
PrivacyVi phạm chính sách dữ liệu người dùng của Google Play
Tương thíchConflict với Autofill Framework hệ thống (Android 8+)
Kiểm soátUser không thể quản lý/xóa mật khẩu đã lưu trong WebView

Giải pháp hiện đại (Khuyến nghị)

1. Sử dụng Autofill Framework (Android 8.0+)

Hệ thống Android cung cấp Autofill service (Google Autofill, Bitwarden, 1Password, LastPass...). WebView tự động hỗ trợ nếu:

  • WebView có android:importantForAutofill="yes" (XML) hoặc setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES).
  • Input fields có autocomplete attribute đúng: username, current-password, new-password, email.
  • User đã bật Autofill service trong Settings.
// Trong WebView setup
webView.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);

// HTML form nên có:
/*
*/

2. Sử dụng WebViewClient.onReceivedLoginRequest (API 21+)

Cho phép app xử lý login form và lưu credential vào Keystore/EncryptedSharedPreferences:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
        // Xử lý login request - có thể hiển thị dialog tự định nghĩa
        // Lưu credential an toàn vào EncryptedSharedPreferences
        super.onReceivedLoginRequest(view, realm, account, args);
    }
});

3. JavaScript Interface để giao tiếp với Native

// Inject JavaScript interface
webView.addJavascriptInterface(new Object() {
    @JavascriptInterface
    public void saveCredentials(String username, String password) {
        // Lưu vào Android Keystore / EncryptedSharedPreferences
        // Chỉ dùng cho trang web KHÁCH QUAN TRỌNG (trusted)
    }
}, "AndroidBridge");

// Trong trang web (chỉ trusted domain):
/*
document.querySelector('form').addEventListener('submit', function(e) {
    const user = document.querySelector('[name="username"]').value;
    const pass = document.querySelector('[name="password"]').value;
    AndroidBridge.saveCredentials(user, pass);
});
*/

4. Sử dụng Credential Manager API (Android 14+ / Jetpack)

// dependencies:
implementation "androidx.credentials:credentials:1.2.0"
implementation "androidx.credentials:credentials-play-services-auth:1.2.0"

// Sử dụng:
CredentialManager credentialManager = CredentialManager.create(this);
// Get/Create credentials, hỗ trợ passkey, password, federated identity

So sánh các phương pháp

Phương phápAPI LevelBảo mậtTích hợp hệ thốngĐộ phức tạp
setSavePassword() (Deprecated)< 26ThấpKhôngĐơn giản
Autofill Framework26+Cao (hệ thống quản lý)Hoàn toànThấp
onReceivedLoginRequest21+Tùy implementTrung bìnhTrung bình
JavaScript InterfaceTất cảRủi ro XSS nếu không cẩn thậnTùy chỉnhCao
Credential Manager (Jetpack)21+ (backport)Rất cao (Keystore, Passkey)Hoàn toànTrung bình

Lưu ý quan trọng

  • KHÔNG BAO GIỜ tự implement lưu mật khẩu plaintext - vi phạm bảo mật cơ bản.
  • Luôn sử dụng Android Keystore hoặc EncryptedSharedPreferences để lưu credential.
  • Chỉ dùng JavaScript Interface cho domain hoàn toàn tin cậy (first-party).
  • Tuân thủ Google Play Policy về dữ liệu người dùng và quyền riêng tư.
  • Test trên nhiều phiên bản Android và các Autofill service khác nhau.