Có an toàn khi đưa Firebase apiKey ra công chúng không?


433

Các hướng dẫn căn cứ hỏa lực Web App khẳng định tôi nên đặt cho apiKeytrong Html tôi để khởi tạo căn cứ hỏa lực:

// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: '<your-api-key>',
    authDomain: '<your-auth-domain>',
    databaseURL: '<your-database-url>',
    storageBucket: '<your-storage-bucket>'
  };
  firebase.initializeApp(config);
</script>

Bằng cách làm như vậy, apiKeytiếp xúc với mọi du khách. Mục đích của khóa đó là gì và nó thực sự có nghĩa là công khai?


1
Tôi nghĩ miễn là bạn thiết lập quy tắc cơ sở dữ liệu Firebase AuthFirebase, bạn có thể cung cấp thông tin đó công khai.
abbaf33f

Người dùng Christophe Quintard đã thêm một liên kết đến một bài viết rất hữu ích với thông tin bổ sung về bảo mật API Firebase, vì vậy tôi đang đăng lại nó ở đây: javebratt.com/ leather-firebase-api (Nhận xét sẽ biến mất vì nó được đính kèm với người dùng khác câu trả lời được gắn cờ để xóa do chất lượng kém)
Oliver Schafeld

Tôi chỉ muốn chỉ ra rằng chỉ vì khung cụ thể này có vẻ ổn khi phơi bày API của nó, điều đó không có nghĩa là các khung khác đều ổn với nó. Sẽ không muốn bất kỳ ai rời khỏi bài đăng này với ý tưởng rằng "Nói chung để lộ các Khóa API" là ổn.
YungGun

bạn để lộ chìa khóa không có vấn đề. Để đảm bảo an toàn, bạn có thể hạn chế nó với tên miền cụ thể trong sản xuất để không ai khác có thể thực hiện cuộc gọi API cuộc gọi từ bất kỳ tên miền ngẫu nhiên nào. Để làm cho nó an toàn hơn, loại bỏ localhost khỏi ứng dụng sản xuất.
BL CK

1
Tôi không nghĩ việc xóa localhost khỏi danh sách trắng giới thiệu của bạn sẽ làm bất cứ điều gì ngoại trừ làm cho việc kiểm tra khó khăn hơn. Cấu hình đó không giống như một danh sách trắng IP; nghĩ về nó giống như một cấu hình CORS. Cách Firebase hoạt động là các tuyến API đó được gọi trực tiếp từ các máy khách, chúng không được ủy quyền. Đó là lý do tại sao trang web của bạn cần khóa API. Nếu một diễn viên xấu muốn gọi các tuyến API của bạn từ Postman, danh sách trắng người giới thiệu của bạn sẽ không ngăn họ. Nó chỉ hữu ích để ngăn chặn các trang web công cộng khác tắt máy chủ của bạn.
forresthopkinsa

Câu trả lời:


448

ApiKey trong đoạn cấu hình này chỉ xác định dự án Firebase của bạn trên các máy chủ của Google. Nó không phải là một rủi ro bảo mật cho ai đó biết nó. Trên thực tế, họ cần phải biết điều đó, để họ tương tác với dự án Firebase của bạn. Dữ liệu cấu hình tương tự này cũng được bao gồm trong mọi ứng dụng iOS và Android sử dụng Firebase làm phụ trợ.

Theo nghĩa đó, nó rất giống với URL cơ sở dữ liệu xác định cơ sở dữ liệu phía sau được liên kết với dự án của bạn trong cùng một đoạn : https://<app-id>.firebaseio.com. Xem câu hỏi này tại sao đây không phải là rủi ro bảo mật: Làm thế nào để hạn chế sửa đổi dữ liệu Firebase? , bao gồm cả việc sử dụng các quy tắc bảo mật phía máy chủ của Firebase để đảm bảo chỉ những người dùng được ủy quyền mới có thể truy cập các dịch vụ phụ trợ.

Nếu bạn muốn tìm hiểu cách bảo mật tất cả quyền truy cập dữ liệu vào các dịch vụ phụ trợ Firebase của bạn được cho phép, hãy đọc tài liệu về các quy tắc bảo mật của Firebase .


Nếu bạn muốn giảm rủi ro cam kết dữ liệu cấu hình này thành kiểm soát phiên bản, hãy xem xét sử dụng cấu hình tự động SDK của Firebase Hosting . Mặc dù các khóa vẫn sẽ kết thúc trong trình duyệt ở cùng định dạng, nhưng chúng sẽ không được mã hóa cứng vào mã của bạn nữa.


7
Vậy có nghĩa là những người khác sẽ có thể truy cập tất cả dữ liệu trong cơ sở dữ liệu căn cứ hỏa lực của tôi?
Emmanuel Campos

31
@EmmanuelCampos Trả lời là Có và Không. Có, nếu bạn cho phép hoặc muốn người khác truy cập tất cả dữ liệu trong cơ sở dữ liệu. Và không, nếu bạn không muốn họ. Cơ sở dữ liệu Firebase có các quy tắc, quy tắc mà bạn kiểm soát
KhoPhi

5
Tìm thấy câu trả lời của tôi ở đây cho câu hỏi cuối cùng của tôi support.google.com.vn/firebase căn hộ / 6400741 Cảm ơn sự giúp đỡ. Liên kết này có thể giúp ai đó trong tương lai.
Emmanuel Campos

7
@ m.rufca, dữ liệu của bạn nên có sẵn cho người dùng, những người được xác thực. Và đây là mẹo. Theo mặc định, trong cài đặt firebase của bạn, chỉ localhost và miền dự án của bạn được ủy quyền để thực hiện xác thực từ chúng. Vì vậy, không ai khác có thể tạo ứng dụng thường hoạt động với căn cứ hỏa lực của bạn.
Artem Arkhipov

15
Điều gì xảy ra nếu bot tạo người dùng không giới hạn tại ứng dụng của tôi. Làm thế nào tôi có thể yêu cầu captcha.
Muhammad Umer

79

Dựa trên câu trả lời của prufrofro và Frank van Puffelen ở đây , tôi kết hợp thiết lập này không ngăn được việc cào, nhưng có thể khiến việc sử dụng khóa API của bạn khó hơn một chút.

Cảnh báo: Để có được dữ liệu của bạn, ngay cả với phương thức này, ví dụ, người ta có thể chỉ cần mở bảng điều khiển JS trong Chrome và gõ:

firebase.database().ref("/get/all/the/data").once("value", function (data) {
    console.log(data.val());
});

Chỉ các quy tắc bảo mật cơ sở dữ liệu có thể bảo vệ dữ liệu của bạn.

Tuy nhiên, tôi đã hạn chế sử dụng khóa API sản xuất cho tên miền của mình như thế này:

  1. https://console.developers.google.com/apis
  2. Chọn dự án Firebase của bạn
  3. Thông tin xác thực
  4. Trong khóa API, chọn khóa Trình duyệt của bạn. Nó sẽ giống như thế này: " Khóa trình duyệt (tự động được tạo bởi Google Service) "
  5. Trong " Chấp nhận yêu cầu từ những người giới thiệu HTTP (trang web) " này, hãy thêm URL của ứng dụng của bạn (ví dụ projectname.firebaseapp.com/*:)

Bây giờ ứng dụng sẽ chỉ hoạt động trên tên miền cụ thể này. Vì vậy, tôi đã tạo một Khóa API khác sẽ riêng tư để phát triển localhost.

  1. Nhấp vào Tạo thông tin đăng nhập> Khóa API

Theo mặc định, như được đề cập bởi Emmanuel Campos, Firebase chỉ có danh sách trắng localhostvà miền lưu trữ Firebase của bạn .


Để đảm bảo rằng tôi không xuất bản khóa API sai, tôi sử dụng một trong các phương pháp sau để tự động sử dụng một trong những phương thức hạn chế hơn trong sản xuất.

Thiết lập cho ứng dụng tạo-phản ứng

Trong /env.development:

REACT_APP_API_KEY=###dev-key###

Trong /env.production:

REACT_APP_API_KEY=###public-key###

Trong /src/index.js

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  // ... 
};

Thiết lập trước đây của tôi cho Webpack:

Tôi sử dụng Webpack để xây dựng ứng dụng sản xuất của mình và tôi đặt khóa API dev của mình bên trong index.htmlgiống như bạn thường làm. Sau đó, bên trong webpack.production.config.jstệp của tôi , tôi thay thế khóa mỗi lần index.htmlđược sao chép vào bản dựng sản xuất:

plugins: [
    new CopyWebpackPlugin([
      {
        transform: function(content, path) {
          return content.toString().replace("###dev-key###", "###public-key###");
        },
        from: './index.html'
      }
    ])
  ]

1
Điều đó có tốt cho bạn không? Đã suy nghĩ để làm điều tương tự cho một ứng dụng Android. Tôi tự hỏi tại sao Firebase không bao gồm điều đó trong phần bảo mật.
steliosf

2
Cho đến nay tôi không có vấn đề gì, nhưng có lẽ cũng không có cuộc tấn công nào
bây giờ là

3
Điều này không được đề cập trong hướng dẫn của họ vì nó sẽ không bảo vệ bạn khỏi bị cào. Tất cả điều này đảm bảo là người khác không thể tạo một ứng dụng web sử dụng căn cứ hỏa lực của bạn để đọc (hoặc ghi) dữ liệu, nếu nó chạy trong một trình duyệt hoạt động tốt bình thường.
tham gia

@thoutbeckers bạn nói đúng, cảm ơn bạn. Tôi đã chỉnh sửa câu trả lời, nhưng để lại phương thức vì nó vẫn có thể hữu ích.
bây giờ là

1
@FrankvanPuffelen Theo những gì tôi hiểu, nó không tạo ra sự khác biệt lớn, nhưng có thể gây khó chịu hơn một chút khi lạm dụng hạn ngạch của bạn, vì trong một trình duyệt hoạt động tốt, khóa API được cung cấp với HTML / JS sẽ chỉ hoạt động theo dự định tên miền và không phải localhost hoặc bất cứ thứ gì khác. Nhưng tôi đồng ý rằng sự bảo vệ bổ sung là không đáng kể so với những gì Firebase đã cung cấp. Tôi sẽ điều chỉnh lại câu trả lời cho một cái gì đó ít kịch tính hơn.
bây giờ

22

Tôi không bị thuyết phục để lộ các khóa bảo mật / cấu hình cho máy khách. Tôi sẽ không gọi nó là an toàn, không phải vì ai đó có thể đánh cắp tất cả thông tin cá nhân từ ngày đầu tiên, bởi vì ai đó có thể yêu cầu quá mức, làm cạn kiệt hạn ngạch của bạn và khiến bạn nợ Google rất nhiều tiền.

Bạn cần suy nghĩ về nhiều khái niệm từ việc hạn chế mọi người không truy cập vào nơi họ không được phép, các cuộc tấn công của DOS, v.v.

Tôi thích máy khách đầu tiên sẽ truy cập vào máy chủ web của bạn hơn, ở đó bạn đặt tường lửa, captcha, cloudflare, bảo mật tùy chỉnh ở giữa máy khách và máy chủ, hoặc giữa máy chủ và căn cứ hỏa lực và bạn sẽ thuận lợi. Ít nhất trước tiên bạn có thể dừng hoạt động nghi ngờ trước khi nó chạm tới căn cứ hỏa lực. Bạn sẽ linh hoạt hơn nhiều.

Tôi chỉ thấy một kịch bản sử dụng tốt để sử dụng cấu hình dựa trên máy khách cho các mục đích sử dụng nội bộ. Ví dụ: bạn có tên miền nội bộ và bạn khá chắc chắn người ngoài không thể truy cập vào đó, vì vậy bạn có thể thiết lập môi trường như trình duyệt -> loại firebase.


10
Nhưng nó không giống như "phơi bày" bất kỳ API REST nào khác phải không? Ý tôi là với URL API REST có sẵn cho người dùng. Họ có thể sử dụng URL để thực hiện bất kỳ yêu cầu nào họ muốn và rút hết hạn ngạch của bạn. Firebase làm gì là sử dụng cấu hình với các phím api để xác định phần phụ trợ của bạn và nó phải có sẵn để người dùng thực hiện yêu cầu.
mbochynski

3
@mbochynski nhưng bạn phần nào có thể yêu cầu trực tiếp đến các tài nguyên khiến bạn phải trả hóa đơn. Và ở phía Firebase không có nhiều cơ chế kiểm soát để ngăn chặn các cuộc tấn công DDoS, v.v. Gợi ý của tôi là hãy để khách hàng gọi API REST của bạn, nhưng API REST đó nên giữ khóa API riêng tư và ngay cả trước khi bạn nhấn tài nguyên Firebase, hãy xác thực chúng nếu chúng là những yêu cầu chính đáng (thông qua Cloudflare, v.v.). hoặc lấy kết quả từ bộ đệm. Sau đó, bạn sẽ chỉ đánh vào tài nguyên Firebase của mình nếu bạn cần. Đây là những gì tôi sẽ triển khai firebase.google.com/docs/admin/setup
Teoman shipahi

3
lộ chìa khóa tại trình duyệt là một ý tưởng tồi. những người viết tất cả những hướng dẫn / bài báo này, họ đã nghĩ gì? http giới thiệu cho bảo mật? điều đó dễ bị giả mạo
Nick Chan Abdullah

1
Các bạn không nghĩ về điều này đúng. Đừng nghĩ về API Key là một bí mật; nó không phải là khóa riêng, nó chỉ là một ID để API Firebase biết ai đang truy cập vào dự án nào. Nếu bạn muốn có nhiều sự linh hoạt và bạn cần kiểm soát từng bước tương tác giữa máy chủ / máy khách thì bạn không nên sử dụng Firebase, bạn nên sử dụng GCP.
forresthopkinsa

@forresthopkinsa Mình có link ở trên bình luận cách tiếp cận nào. Không ai ở đây đủ ngây thơ để đề nghị nó là một chìa khóa bí mật cả.
Teoman shipahi

4

Tôi tin rằng một khi các quy tắc cơ sở dữ liệu được viết chính xác, nó sẽ đủ để bảo vệ dữ liệu của bạn. Hơn nữa, có những hướng dẫn mà người ta có thể làm theo để cấu trúc cơ sở dữ liệu của bạn phù hợp. Ví dụ: tạo một nút UID bên dưới người dùng và đặt tất cả theo thông tin bên dưới nó. Sau đó, bạn sẽ cần thực hiện quy tắc cơ sở dữ liệu đơn giản như dưới đây

  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

Không người dùng nào khác có thể đọc dữ liệu của người dùng khác, hơn nữa, chính sách miền sẽ hạn chế các yêu cầu đến từ các miền khác. Người ta có thể đọc thêm về nó trên các quy tắc bảo mật của Firebase


3

Phơi nhiễm khóa API tạo lỗ hổng khi đăng ký người dùng / mật khẩu được bật. Có một điểm cuối API mở lấy khóa API và cho phép mọi người tạo tài khoản người dùng mới. Sau đó, họ có thể sử dụng tài khoản mới này để đăng nhập vào ứng dụng được bảo vệ Firebase Auth của bạn hoặc sử dụng SDK để xác thực với người dùng / vượt qua và chạy truy vấn.

Tôi đã báo cáo điều này với Google nhưng họ nói nó hoạt động như dự định.

Nếu bạn không thể vô hiệu hóa tài khoản người dùng / mật khẩu, bạn nên làm như sau: Tạo chức năng đám mây để tự động vô hiệu hóa người dùng mới onCreate và tạo mục nhập DB mới để quản lý quyền truy cập của họ.

Ví dụ: MyUsers / {userId} / Access: 0

exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);

Cập nhật quy tắc của bạn để chỉ cho phép đọc cho người dùng có quyền truy cập> 1.

Nếu không có chức năng người nghe không vô hiệu hóa tài khoản đủ nhanh thì các quy tắc đọc sẽ ngăn họ đọc bất kỳ dữ liệu nào.


3

Sau khi đọc nó và sau khi tôi thực hiện một số nghiên cứu về các khả năng, tôi đã đưa ra một cách tiếp cận hơi khác để hạn chế sử dụng dữ liệu của người dùng trái phép:

Tôi cũng lưu người dùng trong DB của mình (và lưu dữ liệu hồ sơ trong đó). Vì vậy, tôi chỉ đặt các quy tắc db như thế này:

".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"

Cách này chỉ người dùng đã lưu trước đó mới có thể thêm người dùng mới vào DB, do đó, không có ai mà không có tài khoản có thể thực hiện các thao tác trên DB. đồng thời thêm người dùng mới chỉ hiển thị nếu người dùng có vai trò đặc biệt và chỉ chỉnh sửa bởi quản trị viên hoặc bởi chính người dùng đó (đại loại như thế này):

"userdata": {
  "$userId": {
    ".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
   ...

-2

Bạn không nên tiết lộ thông tin này. ở nơi công cộng, khóa api đặc biệt. Nó có thể dẫn đến rò rỉ quyền riêng tư.

Trước khi công khai trang web, bạn nên ẩn nó. Bạn có thể làm theo 2 cách trở lên

  1. Mã hóa / ẩn phức tạp
  2. Chỉ cần đặt mã SDK firebase ở dưới cùng của trang web hoặc ứng dụng của bạn để firebase tự động thực hiện tất cả các hoạt động. bạn không cần đặt khóa API ở bất cứ đâu

Tôi trích dẫn từ Firebase, "Sao chép và dán các tập lệnh này vào dưới cùng của thẻ <body> của bạn, nhưng trước khi bạn sử dụng bất kỳ dịch vụ Firebase nào", bao gồm khóa API
Luke-zhang-04
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.