12/08/2018, 14:12

Các thủ thuật để giấu secret key/password khỏi source control và ứng dụng với CI trong lập trình Android

Xin chào các bạn. Chắc hẳn mỗi chúng ta đều đã từng phát triển app sử dụng API của bên thứ 3, và chắc mọi người đều biết là hầu hết các API service đều yêu cầu chúng ta phải có 1 API key (secret token) để verify nguồn gốc của các request. Vậy thì tại sao chúng ta lại phải "giấu" API key này khỏi ...

Xin chào các bạn. Chắc hẳn mỗi chúng ta đều đã từng phát triển app sử dụng API của bên thứ 3, và chắc mọi người đều biết là hầu hết các API service đều yêu cầu chúng ta phải có 1 API key (secret token) để verify nguồn gốc của các request. Vậy thì tại sao chúng ta lại phải "giấu" API key này khỏi các VCS như git? Một trong những lý do quan trọng nhất chính là việc những người khác sẽ có toàn quyền sử dụng API dưới danh nghĩa của bạn, và thậm chí là họ có thể chỉnh sửa các dữ liệu bí mật hay violate các rule của service. Lí do thứ 2 là hầu hết các free service đều áp đặt 1 rate limit lên request; ví dụ 1 API key chỉ được phép thực hiện 60 request trong 1 phút, nên việc những người phát triển app của bạn cùng sử dụng 1 API key sẽ làm cho số request này hết rất nhanh và hiệu suất làm việc sẽ bị giảm đi đáng kể. Ở bài này chúng ta sẽ thảo luận về các cách để "giấu" API key mà không làm hỏng cấu trúc của ứng dụng khi làm việc theo team trên git, cũng như cách để áp dụng các thủ thuật này với các CI như Travis hay Circle.

Cách thường dùng

Cách phổ biến nhất để giấu API key chính là cho nó làm XML resource và đưa vào .gitignore:

1. Đầu tiên chúng ta tạo 1 file XML mới, tạm đặt tên là keys.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="api_key">5093450734057234872347234</string>
</resources>

2. Đọc giá trị của key khi app chạy:

String apiKey = getString(R.string.api_key);

3. Cho path của file này vào .gitignore để git không track nó.

4. Chỉnh sửa file Readme để hướng dẫn mọi người làm theo các bước trên.

Nhìn thì khá là đơn giản, nhưng cách này có rất nhiều nhược điểm:

  • Rắc rối để chỉnh sửa key.
  • Cần cho ra file riêng với tên chính xác là keys.xml và path chính xác để .gitignore hoạt động đúng. Ngoài ra còn cần thêm thuộc tính translatable="false" khi sử dụng nhiều ngôn ngữ.
  • Sẽ không thể build pass CI vì lỗi thiếu resource.

Cách tốt hơn: Sử dụng gradle.properties

gradle.properties là file chứa các setting để configure build environment của Gradle. File này sẽ được đọc ra khi gradle build project của bạn. Chúng ta sẽ lợi dụng điều này để định nghĩa các API key:

1. Thêm API key vào gradle.properties:

API_KEY=5093450734057234872347234

2. Gán giá trị vào biến trong file build.gradle của module (app/build.gradle)

android {
    defaultConfig {
        buildConfigField "String", "API_KEY", ""${API_KEY}""
        //Lí do chúng ta phải sử dụng  là để kèm escape character " " vào chuỗi String
    }
}

Khi build project, gradle sẽ tự generate ra 1 file tên BuildConfig.java với các thông tin của build.gradle:

public final class BuildConfig {
    public static final String API_KEY = "5093450734057234872347234";
}

3. Sử dụng trong Java:

String apiKey = BuildConfig.API_KEY;

4. Chúng ta cần commit file này lên git, vì thế đầu tiên chúng ta phải "giấu" key thật đi như sau:

gradle.properties

API_KEY=INSERT_YOUR_API_KEY_HERE

5. git add, git commit và push lên upstream như bình thường.

6. Sử dụng lệnh git update-index --skip-worktree gradle.properties . Về cơ bản thì lệnh này sẽ nói với git là "Đừng quan tâm đến bất kì thay đổi nào trong file gradle.properties, luôn luôn sử dụng file ở local và không pull những thay đổi từ upstream về đối với file này".

7. Sửa lại gradle.properties để dùng lại API thực của chúng ta:

API_KEY=5093450734057234872347234

Sau đó bạn thử dùng git status xem, git sẽ nói là không có bất kì thay đổi nào ở local             </div>
            
            <div class=

0