Lớp học lập trình về cấu hình bảo mật mạng trên Android

1. Giới thiệu

Trao đổi dữ liệu qua Internet là hoạt động bình thường của các ứng dụng. Do ứng dụng của bạn có khả năng sẽ giao tiếp với các máy chủ không phải là những máy chủ mà ứng dụng tin tưởng, bạn cần phải thận trọng khi gửi và nhận thông tin có thể là thông tin nhạy cảm và riêng tư.

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ xây dựng một ứng dụng hiển thị tin nhắn. Mỗi tin nhắn sẽ chứa tên người gửi, tin nhắn văn bản và URL tới "ảnh hồ sơ" của họ. Ứng dụng sẽ hiển thị những tin nhắn này bằng cách thực hiện các hành động sau:

  • Tải một tệp JSON chứa danh sách tin nhắn văn bản từ mạng.
  • Tải từng ảnh hồ sơ và hiển thị ảnh đó bên cạnh tin nhắn thích hợp.

Kiến thức bạn sẽ học được

  • Tại sao việc bảo mật khi giao tiếp qua mạng quan trọng.
  • Cách sử dụng thư viện Volley để tạo yêu cầu mạng.
  • Cách sử dụng Cấu hình bảo mật mạng để giúp việc giao tiếp qua mạng trở nên an toàn hơn.
  • Cách sửa đổi một số tuỳ chọn nâng cao về Cấu hình bảo mật mạng. Những tuỳ chọn này sẽ hữu ích trong quá trình phát triển và kiểm thử.
  • Khám phá một trong những vấn đề thường gặp nhất về bảo mật mạng và xem cách Cấu hình bảo mật mạng có thể giúp ngăn chặn vấn đề đó.

Bạn cần có

  • Phiên bản mới nhất của Android Studio
  • Một thiết bị Android hoặc trình mô phỏng chạy Android 7.0 (API cấp 24) trở lên
  • Node.js (hoặc quyền truy cập vào một máy chủ web có thể định cấu hình)

Nếu bạn gặp vấn đề (lỗi trong đoạn mã, lỗi ngữ pháp, từ ngữ không rõ ràng, v.v.) khi thực hành theo lớp học lập trình này, vui lòng báo cáo vấn đề thông qua đường liên kết Báo cáo lỗi ở góc dưới bên trái lớp học lập trình.

2. Chuẩn bị

Tải mã nguồn xuống

Nhấp vào đường liên kết sau đây để tải toàn bộ mã nguồn cho lớp học lập trình này:

Giải nén tệp zip đã tải xuống. Thao tác này sẽ giải nén thư mục gốc (android-network-secure-config), thư mục này chứa dự án Android Studio (SecureConfig/) và một số tệp dữ liệu mà chúng ta sẽ sử dụng trong giai đoạn sau (server/).

Bạn cũng có thể trực tiếp xem các đoạn mã qua GitHub: (Bắt đầu bằng nhánh master.)

Chúng tôi cũng đã chuẩn bị một nhánh có đoạn mã hoàn chỉnh sau mỗi bước. Nếu bạn gặp khó khăn, hãy xem các nhánh trên GitHub hoặc sao chép toàn bộ kho lưu trữ: https://github.com/android/codelab-android-network-security-config/branches/all

3. Chạy ứng dụng

Sau khi bạn nhấp vào biểu tượng "tải", ứng dụng này sẽ truy cập máy chủ từ xa để tải danh sách tin nhắn, tên và URL tới ảnh hồ sơ của người dùng qua tệp JSON. Tiếp theo, các tin nhắn sẽ xuất hiện trong danh sách và ứng dụng tải hình ảnh qua các URL được tham chiếu đến.

Lưu ý: Ứng dụng mà chúng tôi đang sử dụng trong lớp học lập trình này chỉ dành cho mục đích minh hoạ. Hoạt động xử lý lỗi ở đây sẽ không nhiều bằng công việc thực tế cần thiết trong môi trường phát hành công khai.

d9e465c94b420ea1.png

Cấu trúc ứng dụng

Ứng dụng tuân theo mô hình MVP, phân tách nơi lưu trữ dữ liệu và quyền truy cập mạng (mô hình) khỏi logic (trình thể hiện) và màn hình (chế độ xem).

Lớp MainContract chứa hợp đồng mô tả giao diện giữa Chế độ xem và Trình thể hiện:

MainContract.java

/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.networksecurity;

import com.example.networksecurity.model.Post;

/**
 * Contract defining the interface between the View and Presenter.
 */
public interface MainContract {

    interface View {
        /**
         * Sets the presenter for interaction from the View.
         *
         * @param presenter
         */
        void setPresenter(Presenter presenter);

        /**
         * Displays or hides a loading indicator.
         *
         * @param isLoading If true, display a loading indicator, hide it otherwise.
         */
        void setLoadingPosts(boolean isLoading);

        /**
         * Displays a list of posts on screen.
         *
         * @param posts The posts to display. If null or empty, the list should not be shown.
         */
        void setPosts(Post[] posts);

        /**
         * Displays an error message on screen and optionally prints out the error to logcat.
         */
        void showError(String title, String error);

        /**
         * Hides the error message.
         *
         * @see #showError(String, String)
         */
        void hideError();

        /**
         * Displays an empty message and icon.
         *
         * @param showMessage If true, the message is show. If false, the message is hidden
         */
        void showNoPostsMessage(boolean showMessage);
    }

    interface Presenter {
        /**
         * Call to start the application. Sets up initial state.
         */
        void start();

        /**
         * Loads post for display.
         */
        void loadPosts();

        /**
         * An error was encountered during the loading of profile images.
         */
        void onLoadPostImageError(String error, Exception e);
    }

}

Cấu hình ứng dụng

Nhằm mục đích minh hoạ, chúng tôi đã tắt mọi tính năng lưu vào bộ nhớ đệm của mạng cho ứng dụng này. Tốt nhất là trong môi trường phát hành công khai, ứng dụng sẽ sử dụng một bộ nhớ đệm cục bộ để giới hạn số lượng yêu cầu mạng từ xa.

Tệp gradle.properties chứa URL mà danh sách tin nhắn sẽ được tải qua đó:

gradle.properties

postsUrl="http://storage.googleapis.com/network-security-conf-codelab.appspot.com/v1/posts.json"

Xây dựng và chạy ứng dụng

  1. Khởi động Android Studio rồi mở thư mục SecureConfig dưới dạng một dự án Android.
  2. Nhấp vào "chạy" để khởi động ứng dụng: e15973f44eed7cc2.png

Ảnh chụp màn hình sau đây cho thấy giao diện của ứng dụng trên thiết bị:

63300e7e262bd161.pngs

4. Cấu hình bảo mật mạng cơ bản

Trong bước này, chúng ta sẽ thiết lập một cấu hình bảo mật mạng cơ bản và quan sát một lỗi xảy ra khi một trong các quy tắc trong cấu hình bị vi phạm.

Tổng quan

Cấu hình bảo mật mạng cho phép các ứng dụng tuỳ chỉnh chế độ cài đặt bảo mật mạng thông qua tệp cấu hình khai báo. Toàn bộ cấu hình đều nằm trong tệp XML này và bạn không cần phải thay đổi mã của nó.

Đoạn mã này cho phép định cấu hình những mục sau:

  • Chọn không sử dụng lưu lượng truy cập qua văn bản thô: Vô hiệu hoá lưu lượng truy cập qua văn bản thô.
  • Neo tin cậy tuỳ chỉnh: Chỉ định tổ chức phát hành chứng chỉ và các nguồn mà ứng dụng tin tưởng.
  • Ghi đè chế độ chỉ gỡ lỗi: Gỡ lỗi kết nối bảo mật một cách an toàn mà không ảnh hưởng đến bản phát hành.
  • Ghim chứng chỉ: Hạn chế các kết nối an toàn trong một số chứng chỉ cụ thể.

Bạn có thể sắp xếp tệp theo miền, cho phép áp dụng các chế độ cài đặt bảo mật mạng cho tất cả URL hoặc chỉ cho một số miền cụ thể.

Cấu hình bảo mật mạng có trên Android 7.0 (API cấp 24) trở lên.

Tạo tệp XML cấu hình bảo mật mạng

Tạo một tệp tài nguyên xml mới có tên network_security_config.xml.

Trong Android Project Panel (Bảng điều khiển dự án Android) ở bên trái, hãy nhấp chuột phải vào res, sau đó chọn New (Mới) > Android resource file (Tệp tài nguyên Android).

35db6786b96a6980.png

Thiết lập các tuỳ chọn sau đây rồi nhấp vào OK.

Tên tệp

network_security_config.xml

Loại tài nguyên

XML

Thành phần gốc

network-security-config

Tên thư mục

xml

36ae9e950fe66f1c.png

Mở tệp xml/network_security_config.xml (nếu tệp này không tự động mở).

Thay thế nội dung của tệp bằng đoạn mã sau:

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false" >
    </base-config>
</network-security-config>

Cấu hình này áp dụng cho cấu hình cơ sở (hay cấu hình bảo mật mặc định) của ứng dụng và vô hiệu hoá tất cả lưu lượng truy cập qua văn bản thô.

Bật cấu hình bảo mật mạng

Tiếp theo, hãy thêm nội dung tham chiếu đến cấu hình ứng dụng trong tệp AndroidManifest.xml.

Mở tệp AndroidManifest.xml rồi tìm phần tử application trong tệp đó.

Trước tiên, hãy xoá dòng đặt thuộc tính android:usesCleartextTraffic="true".

Tiếp theo, hãy thêm thuộc tính android:networkSecurityConfig vào phần tử application trong AndroidManifest, tham chiếu tài nguyên tệp XML network_security_config: @xml/network_security_config

Sau khi xoá và thêm hai thuộc tính trên, thẻ mở ứng dụng sẽ có dạng như sau:

AndroidManifest.xml

<application
    android:networkSecurityConfig="@xml/network_security_config"
    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"
    android:fullBackupContent="false"
    tools:ignore="GoogleAppIndexingWarning">
    ...

Biên dịch và chạy ứng dụng

Biên dịch và chạy ứng dụng.

Bạn sẽ thấy một thông báo lỗi – ứng dụng đang cố gắng tải dữ liệu qua một kết nối văn bản thô (cleartext connection)!

98d8a173d5293742.png

Trong logcat, bạn sẽ thấy lỗi này:

java.io.IOException: Cleartext HTTP traffic to storage.googleapis.com not permitted

Ứng dụng này không tải dữ liệu vì ứng dụng vẫn được định cấu hình để tải danh sách tin nhắn qua một kết nối HTTP chưa mã hoá. URL được định cấu hình trong tệp gradle.properties trỏ đến máy chủ HTTP không sử dụng TLS!

Hãy thay đổi URL này để sử dụng một máy chủ khác và tải dữ liệu qua một kết nối HTTPS bảo mật.

Thay đổi tệp gradle.properties như sau:

gradle.properties

postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v1/posts.json"

(Chú ý: giao thức trong URL là giao thức https).

Có thể bạn sẽ phải dựng lại dự án để thay đổi này có hiệu lực. Trên trình đơn, hãy chọn Build > Rebuild.

Chạy lại ứng dụng. Giờ bạn sẽ thấy ứng dụng tải dữ liệu vì yêu cầu mạng sử dụng kết nối HTTPS:

63300e7e262bd161.pngs

5. Vấn đề thường gặp: Cập nhật phía máy chủ

Cấu hình bảo mật mạng có thể chống lại các lỗ hổng bảo mật khi ứng dụng tạo yêu cầu qua một kết nối không an toàn.

Một vấn đề phổ biến khác mà Cấu hình bảo mật mạng giải quyết là các thay đổi phía máy chủ ảnh hưởng đến các URL được tải vào một ứng dụng Android. Ví dụ: trong ứng dụng của chúng ta, hãy hình dung máy chủ bắt đầu trả về URL không an toàn loại HTTP cho ảnh hồ sơ thay vì URL an toàn loại HTTPS. Một cấu hình bảo mật mạng thực thi các kết nối HTTPS sẽ tạo ra một ngoại lệ vì yêu cầu này sẽ chưa được đáp ứng trong thời gian chạy.

Cập nhật phần phụ trợ của ứng dụng

Như bạn đã biết, trước tiên, ứng dụng tải một danh sách tin nhắn, mỗi tin nhắn tham chiếu tới một URL ảnh hồ sơ.

Hãy hình dung đã có thay đổi đối với dữ liệu mà ứng dụng tiêu thụ, khiến ứng dụng yêu cầu nhiều URL hình ảnh. Hãy mô phỏng sự thay đổi này bằng cách sửa đổi URL của dữ liệu phụ trợ.

Thay đổi tệp gradle.properties như sau:

gradle.properties

postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v2/posts.json"

(Chú ý: đường dẫn có phần tử "v2"!)

Có thể bạn sẽ phải dựng lại dự án để thay đổi này có hiệu lực. Trên trình đơn, hãy chọn Build > Rebuild.

Bạn có thể truy cập vào phần phụ trợ "mới" trên trình duyệt để xem tệp JSON đã sửa đổi. Hãy chú ý đến việc tất cả URL được tham chiếu sử dụng HTTP thay vì HTTPS.

Chạy ứng dụng và kiểm tra lỗi

Biên dịch và chạy ứng dụng.

Ứng dụng tải tin nhắn nhưng lại không tải hình ảnh. Hãy kiểm tra thông báo lỗi trong ứng dụng và trong logcat để xem lý do:

a2a98a842e99168d.png

java.io.IOException: Cleartext HTTP traffic to storage.googleapis.com not permitted

Ứng dụng vẫn sử dụng HTTPS để truy cập vào tệp JSON. Tuy nhiên, đường liên kết đến hình ảnh hồ sơ bên trong tệp JSON sử dụng địa chỉ HTTP, vì vậy, ứng dụng cố gắng tải hình ảnh qua HTTP (không an toàn).

Bảo vệ dữ liệu

Cấu hình bảo mật mạng đã ngăn chặn thành công tình trạng rò rỉ dữ liệu ngoài ý muốn. Thay vì cố gắng truy cập dữ liệu không an toàn, ứng dụng sẽ chặn nỗ lực kết nối.

Hãy hình dung một tình huống như thế này, khi sự thay đổi trong phần phụ trợ chưa được kiểm thử đầy đủ trước khi phát hành. Việc áp dụng Cấu hình bảo mật mạng cho ứng dụng Android có thể ngăn các vấn đề tương tự xảy ra, ngay cả sau khi ứng dụng được phát hành.

Thay đổi phần phụ trợ để sửa ứng dụng

Thay đổi URL phụ trợ thành phiên bản mới đã được sửa. Ví dụ này mô phỏng cách khắc phục bằng cách tham chiếu ảnh hồ sơ bằng URL HTTPS.

Thay đổi URL phụ trợ trong tệp gradle.properties và làm mới dự án:

gradle.properties

postsUrl="https://storage.googleapis.com/network-security-conf-codelab.appspot.com/v3/posts.json"

(Chú ý: trong đường dẫn có phần tử v3!)

Chạy lại ứng dụng. Giờ đây ứng dụng hoạt động như mong đợi:

63300e7e262bd161.pngs

6. Cấu hình theo miền cụ thể

Cho đến nay, chúng ta đã chỉ định cấu hình bảo mật mạng trong base-config, tức là sẽ áp dụng cấu hình này cho tất cả đường kết nối mà ứng dụng cố gắng tạo ra.

Bạn có thể ghi đè cấu hình này cho một số đích đến cụ thể bằng cách chỉ định một phần tử domain-config. domain-config khai báo các tuỳ chọn cấu hình cho một nhóm miền cụ thể.

Hãy cập nhật cấu hình bảo mật mạng trong ứng dụng của chúng ta theo nội dung sau:

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false" />
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">localhost</domain>
    </domain-config>
</network-security-config>

Cấu hình này áp dụng base-config cho mọi miền, ngoại trừ miền "localhost" và các miền con của miền đó (áp dụng một cấu hình khác).

Ở đây, cấu hình cơ sở ngăn chặn lưu lượng truy cập qua văn bản thô trên mọi miền. Tuy nhiên, cấu hình miền sẽ ghi đè quy tắc đó, cho phép ứng dụng truy cập localhost bằng cách sử dụng văn bản thô.

Kiểm thử bằng máy chủ HTTP cục bộ

Bây giờ, khi ứng dụng có thể dùng văn bản thô để truy cập vào localhost, hãy khởi động một máy chủ web cục bộ và kiểm thử giao thức truy cập này.

Có nhiều công cụ giúp bạn lưu trữ một máy chủ web rất cơ bản, chẳng hạn như Node.JS, Python và Perl. Trong lớp học lập trình này, chúng ta sẽ dùng mô-đun Node.JS http-server để phân phát dữ liệu cho ứng dụng.

  1. Mở cửa sổ dòng lệnh rồi cài đặt http-server:
npm install http-server -g
  1. Chuyển đến thư mục mà bạn đã kiểm tra mã, sau đó chuyển đến thư mục server/:
cd server/
  1. Khởi động máy chủ web rồi phân phát các tệp trong thư mục/dữ liệu:
http-server ./data -p 8080
  1. Mở trình duyệt web rồi chuyển đến http://localhost:8080 để xác minh rằng bạn có thể truy cập vào các tệp và xem tệp "posts.json":

934e48553bcc48e7.png

  1. Tiếp theo, chuyển tiếp cổng 8080 từ thiết bị sang máy cục bộ. Chạy lệnh sau đây trong một cửa sổ dòng lệnh khác:
adb reverse tcp:8080 tcp:8080

Ứng dụng của bạn hiện có thể truy cập vào "localhost:8080" qua thiết bị Android.

  1. Thay đổi URL dùng để tải dữ liệu trong ứng dụng để trỏ đến máy chủ mới trên localhost. Thay đổi tệp gradle.properties như sau: (Hãy nhớ rằng có thể bạn sẽ phải đồng bộ hoá dự án gradle sau khi thay đổi tệp này.)

gradle.properties

postsUrl="http://localhost:8080/posts.json"
  1. Chạy ứng dụng và xác minh rằng dữ liệu được tải qua máy cục bộ. Bạn có thể thử sửa đổi tệp data/posts.json rồi làm mới ứng dụng để chắc chắn rằng cấu hình mới đang hoạt động như dự kiến.

63300e7e262bd161.pngs

Ngoài ra – cấu hình của miền

Bạn có thể xác định các tuỳ chọn cấu hình áp dụng cho miền cụ thể trong phần tử domain-config. Phần tử này có thể chứa nhiều mục domain chỉ định nơi áp dụng quy tắc domain-config. Nếu nhiều phần tử domain-config chứa các mục domain tương tự, thì Cấu hình bảo mật mạng sẽ chọn một cấu hình để áp dụng cho một URL nhất định dựa trên số lượng ký tự trùng khớp. Cấu hình chứa mục domain khớp với nhiều ký tự nhất (liên tiếp) so với URL được sử dụng.

Cấu hình miền có thể áp dụng cho nhiều miền và cũng có thể bao gồm các miền con.

Ví dụ sau đây cho thấy một Cấu hình bảo mật mạng chứa nhiều miền. (Chúng ta sẽ không thay đổi ứng dụng. Đây chỉ là một ví dụ!)

<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">secure.example.com</domain>
        <domain includeSubdomains="true">cdn.example.com</domain>
        <trust-anchors>
            <certificates src="@raw/trusted_roots"/>
        </trust-anchors>
    </domain-config>
</network-security-config>

Để biết thêm chi tiết, hãy tham khảo định nghĩa định dạng tệp cấu hình.

7. Ghi đè chế độ gỡ lỗi

Khi phát triển và kiểm thử một ứng dụng được thiết kế để đưa ra các yêu cầu qua HTTPS, có thể bạn sẽ phải kết nối ứng dụng đó với một máy chủ web cục bộ hoặc môi trường kiểm thử, như chúng ta đã thực hiện trong bước trước.

Thay vì thêm một quy trình sử dụng chung chấp nhận lưu lượng truy cập qua văn bản thô trong trường hợp sử dụng này hoặc sửa đổi mã, tuỳ chọn debug-override trong Cấu hình bảo mật mạng cho phép bạn đặt các tuỳ chọn bảo mật chỉ áp dụng khi ứng dụng chạy ở chế độ gỡ lỗi; nghĩa là khi android:debuggable là đúng. Cách này an toàn hơn nhiều so với việc sử dụng mã có điều kiện do cách này chỉ rõ định nghĩa chế độ chỉ gỡ lỗi. Cửa hàng Play cũng ngăn chặn việc tải các ứng dụng có thể gỡ lỗi lên, giúp tuỳ chọn này còn an toàn hơn nữa.

Bật SSL trên máy chủ web cục bộ

Trước đó, chúng ta đã khởi động một máy chủ web cục bộ phân phát dữ liệu qua HTTP trên cổng 8080. Bây giờ, chúng ta sẽ tạo một chứng chỉ SSL tự ký rồi sử dụng chứng chỉ này để phân phối dữ liệu qua HTTPS:

  1. Tạo chứng chỉ bằng cách thay đổi thư mục server/ trong cửa sổ dòng lệnh, sau đó thực thi các lệnh sau: (Nếu vẫn đang chạy máy chủ http, bạn có thể dừng máy chủ này ngay bằng cách nhấn vào [CTRL] + [C].)
# Run these commands from inside the server/ directory!

# Create a certificate authority
openssl genrsa -out root-ca.privkey.pem 2048
# Sign the certificate authority
openssl req -x509 -new -nodes -days 100 -key root-ca.privkey.pem -out root-ca.cert.pem -subj "/C=US/O=Debug certificate/CN=localhost" -extensions v3_ca -config openssl_config.txt
# create DER format crt for Android
openssl x509 -outform der -in root-ca.cert.pem -out debug_certificate.crt

Thao tác này sẽ tạo ra một tổ chức phát hành chứng chỉ, ký và tạo một chứng chỉ ở định dạng DER mà Android yêu cầu.

  1. Khởi động máy chủ web bằng HTTPS bằng các chứng chỉ mới tạo:
http-server ./data --ssl --cert root-ca.cert.pem --key root-ca.privkey.pem

Cập nhật URL phụ trợ

Thay đổi ứng dụng để truy cập vào máy chủ localhost qua HTTPS.

Thay đổi tệp gradle.properties:

gradle.properties

postsUrl="https://localhost:8080/posts.json"

Biên dịch và chạy ứng dụng.

Ứng dụng sẽ không hoạt động được khi có lỗi do chứng chỉ của máy chủ không hợp lệ:

3bcce1390e354724.png

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Ứng dụng không thể truy cập vào máy chủ web vì máy chủ này đang sử dụng một chứng chỉ tự ký không đáng tin cậy trong hệ thống. Thay vì tắt HTTPS, chúng ta sẽ thêm chứng chỉ tự ký này cho miền localhost trong bước tiếp theo.

Tham chiếu đến một tổ chức phát hành chứng chỉ tuỳ chỉnh

Máy chủ web đang phân phát dữ liệu qua một tổ chức phát hành chứng chỉ (CA) tự ký không được thiết bị nào chấp nhận theo mặc định. Nếu truy cập vào máy chủ qua trình duyệt, bạn sẽ thấy một cảnh báo bảo mật: https://localhost:8080

898b69ea4fe9bc21.png

Tiếp theo, chúng ta sẽ sử dụng một tuỳ chọn debug-overrides trong cấu hình bảo mật mạng để chỉ chấp nhận tổ chức phát hành chứng chỉ tuỳ chỉnh này cho miền localhost:

  1. Hãy thay đổi tệp xml/network_security_config.xml để tệp này chứa nội dung sau:

res/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="false" />
    <debug-overrides>
        <trust-anchors>
            <!-- Trust a debug certificate in addition to the system certificates -->
            <certificates src="system" />
            <certificates src="@raw/debug_certificate" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

Cấu hình này vô hiệu hoá lưu lượng truy cập qua văn bản thô, và đối với các bản gỡ lỗi*,* chấp nhận tổ chức phát hành chứng chỉ do hệ thống cung cấp cũng như tệp chứng chỉ được lưu trữ trong thư mục res/raw.

Lưu ý: Cấu hình gỡ lỗi ngầm thêm <certificates src="system" />, vì vậy, ứng dụng sẽ hoạt động ngay cả khi không có mã đó. Chúng tôi đã thêm mã đó để cho bạn thấy cách bạn có thể thêm mã đó trong một cấu hình nâng cao hơn.

  1. Tiếp theo, hãy sao chép tệp "debug_certificate.crt" từ thư mục server/ vào thư mục tài nguyên res/raw của ứng dụng trong Android Studio. Bạn cũng có thể kéo và thả tệp vào đúng vị trí trong Android Studio.

Bạn có thể phải tạo thư mục này trước nếu chưa có.

Từ máy chủ/thư mục, bạn có thể chạy các lệnh sau để thực hiện việc này, nếu không, hãy sử dụng một trình quản lý tệp hoặc Android Studio để tạo thư mục và sao chép tệp vào đúng vị trí:

mkdir  ../SecureConfig/app/src/main/res/raw/
cp debug_certificate.crt ../SecureConfig/app/src/main/res/raw/

Android Studio giờ đây sẽ liệt kê tệp debug_certificate.crt trong app/res/raw:

c3111ae17558e167.png

Chạy ứng dụng

Biên dịch và chạy ứng dụng. Giờ đây, ứng dụng này dùng một chứng chỉ gỡ lỗi tự ký để truy cập máy chủ web cục bộ qua HTTPS.

Nếu bạn gặp lỗi, hãy kiểm tra kỹ kết quả logcat và đảm bảo rằng bạn đã khởi động lại http-server với các tuỳ chọn dòng lệnh mới. Ngoài ra, hãy kiểm tra xem tệp debug_certificate.crt có nằm đúng vị trí không (res/raw/debug_certificate.crt).

63300e7e262bd161.pngs

8. Tìm hiểu thêm

Cấu hình bảo mật mạng hỗ trợ thêm nhiều tính năng nâng cao, có thể kể đến một số tính năng như sau:

Khi sử dụng các tính năng này, hãy tham khảo tài liệu để nắm được thông tin chi tiết về các phương pháp hay nhất cũng như các hạn chế.

Tăng cường bảo mật cho ứng dụng!

Trong lớp học lập trình này, bạn đã tìm hiểu cách sử dụng Cấu hình bảo mật mạng để làm cho ứng dụng Android an toàn hơn. Hãy nghĩ về cách vận dụng những tính năng này vào ứng dụng của bạn cũng như cách bạn có thể hưởng lợi từ một cấu hình gỡ lỗi mạnh mẽ hơn để kiểm thử và phát triển.

Tìm hiểu thêm