Cho phép gửi yêu cầu

Yêu cầu gửi tới FCM từ máy chủ ứng dụng hoặc môi trường đáng tin cậy phải được uỷ quyền. Lưu ý những khác biệt quan trọng sau đây giữa uỷ quyền API HTTP cũ và API HTTP phiên bản 1:

  • FCM HTTP v1 API cho phép các yêu cầu bằng mã truy cập OAuth 2.0 ngắn hạn. Để đúc mã thông báo này, bạn có thể sử dụng Ứng dụng Google Thông tin xác thực mặc định (trong môi trường máy chủ của Google) và/hoặc lấy thông tin xác thực theo cách thủ công thông tin đăng nhập bắt buộc từ tệp khoá riêng tư JSON được tạo cho một tài khoản dịch vụ. Nếu bạn đang sử dụng SDK quản trị của Firebase để gửi thông báo, thư viện sẽ xử lý mã thông báo cho bạn.
  • Các giao thức cũ không dùng nữa chỉ có thể sử dụng các khoá API tồn tại lâu dài đã nhận được trong bảng điều khiển của Firebase.

Cho phép yêu cầu gửi HTTP v1

Tuỳ thuộc vào thông tin chi tiết của môi trường máy chủ, hãy sử dụng kết hợp các chiến lược này để cấp quyền cho máy chủ các yêu cầu đến dịch vụ Firebase:

  • Thông tin xác thực mặc định của ứng dụng trên Google (ADC)
  • Tệp JSON của tài khoản dịch vụ
  • Mã truy cập OAuth 2.0 ngắn hạn được lấy từ tài khoản dịch vụ

Nếu ứng dụng của bạn đang chạy trên Compute Engine, Google Kubernetes Engine, App Engine hoặc Cloud Functions (bao gồm Cloud Functions cho Firebase), hãy sử dụng Thông tin xác thực mặc định của ứng dụng (ADC). ADC sử dụng dịch vụ mặc định hiện có của bạn tài khoản của bạn để lấy thông tin đăng nhập để ủy quyền cho các yêu cầu và ADC cho phép kiểm thử cục bộ linh hoạt thông qua biến môi trường GOOGLE_APPLICATION_CREDENTIALS. Để tự động hoá tối đa quy trình uỷ quyền, hãy sử dụng ADC cùng với thư viện máy chủ SDK dành cho quản trị viên.

Nếu ứng dụng của bạn đang chạy trên môi trường máy chủ không phải của Google, bạn sẽ cần tải tệp JSON của tài khoản dịch vụ xuống từ dự án Firebase của mình. Miễn là bạn có quyền truy cập vào hệ thống tệp chứa tệp khóa riêng tư, bạn có thể sử dụng biến môi trường GOOGLE_APPLICATION_CREDENTIALS để cho phép các yêu cầu bằng các thông tin xác thực được thu thập theo cách thủ công này. Nếu bạn thiếu quyền truy cập tệp đó, bạn phải tham chiếu tệp tài khoản dịch vụ trong mã của mình— Việc này nên được thực hiện thật cẩn thận do có nguy cơ làm lộ thông tin đăng nhập của bạn.

Cung cấp thông tin đăng nhập qua ADC

Thông tin đăng nhập mặc định của ứng dụng trên Google (ADC) kiểm tra thông tin đăng nhập của bạn theo thứ tự sau:

  1. ADC kiểm tra xem biến môi trường Đã đặt GOOGLE_APPLICATION_CREDENTIALS. Nếu biến được đặt, ADC sử dụng tệp tài khoản dịch vụ mà biến trỏ đến.

  2. Nếu bạn không đặt biến môi trường, ADC sẽ sử dụng tài khoản dịch vụ mặc định Compute Engine, Google Kubernetes Engine, App Engine, và Cloud Functions cung cấp các ứng dụng chạy trên các dịch vụ đó.

  3. Nếu ADC không thể sử dụng thông tin đăng nhập nào ở trên, thì hệ thống sẽ gửi thông báo lỗi.

Ví dụ về mã SDK dành cho quản trị viên sau đây minh hoạ chiến lược này. Ví dụ không chỉ định rõ ràng thông tin xác thực ứng dụng. Tuy nhiên, ADC có thể ngầm tìm thông tin đăng nhập miễn là biến môi trường được thiết lập, hoặc miễn là ứng dụng đang chạy trên Compute Engine, Google Kubernetes Engine, App Engine hoặc Cloud Functions.

Node.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

Tiến hành

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
});

Cung cấp thông tin đăng nhập theo cách thủ công

Các dự án Firebase hỗ trợ Google tài khoản dịch vụ, mà bạn có thể dùng để gọi Firebase từ máy chủ ứng dụng hoặc môi trường đáng tin cậy. Nếu bạn đang phát triển lập trình cục bộ hoặc triển khai ứng dụng tại chỗ, bạn có thể sử dụng thông tin đăng nhập có được thông qua tài khoản dịch vụ này để uỷ quyền cho các yêu cầu máy chủ.

Để xác thực tài khoản dịch vụ và uỷ quyền tài khoản đó để truy cập các dịch vụ của Firebase, bạn phải tạo một tệp khoá riêng tư ở định dạng JSON .

Cách tạo tệp khoá riêng tư cho tài khoản dịch vụ:

  1. Trong bảng điều khiển của Firebase, hãy mở Cài đặt > Tài khoản dịch vụ.

  2. Nhấp vào Generate New Private Key (Tạo khoá riêng tư mới), sau đó xác nhận bằng cách nhấp vào Generate key (Tạo khoá).

  3. Lưu trữ an toàn tệp JSON chứa khoá.

Khi uỷ quyền qua tài khoản dịch vụ, bạn có hai lựa chọn để cung cấp vào ứng dụng của bạn. Bạn có thể đặt GOOGLE_APPLICATION_CREDENTIALS biến môi trường, hoặc bạn có thể chuyển đường dẫn đến khoá tài khoản dịch vụ trong mã một cách rõ ràng. Lựa chọn đầu tiên an toàn hơn và được khuyên dùng.

Cách đặt biến môi trường:

Đặt biến môi trường GOOGLE_APPLICATION_CREDENTIALS vào đường dẫn tệp của tệp JSON chứa khoá tài khoản dịch vụ của bạn. Biến này chỉ áp dụng cho phiên shell hiện tại của bạn, vì vậy nếu bạn mở một phiên mới, hãy đặt lại biến.

Linux hoặc macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

Với PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

Sau khi bạn hoàn tất các bước trên, Thông tin xác thực mặc định của ứng dụng (ADC) có thể xác định một cách ngầm ẩn các thông tin xác thực của bạn, cho phép bạn sử dụng dịch vụ thông tin đăng nhập tài khoản khi thử nghiệm hoặc chạy trong các môi trường không phải của Google.

Dùng thông tin xác thực để đúc mã truy cập

Trừ phi bạn đang sử dụng SDK dành cho quản trị viên, để tự động xử lý việc uỷ quyền, bạn sẽ cần đúc mã truy cập rồi thêm đường liên kết đó để gửi yêu cầu.

Sử dụng thông tin đăng nhập Firebase của bạn cùng với Thư viện xác thực của Google cho ngôn ngữ bạn muốn dùng để truy xuất mã truy cập OAuth 2.0 ngắn hạn:

nút.js

 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    const key = require('../placeholders/service-account.json');
    const jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

Trong ví dụ này, thư viện ứng dụng API của Google sẽ xác thực yêu cầu bằng mã thông báo web JSON hay JWT. Để biết thêm thông tin, hãy xem Mã thông báo web JSON.

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = service_account.Credentials.from_service_account_file(
    'service-account.json', scopes=SCOPES)
  request = google.auth.transport.requests.Request()
  credentials.refresh(request)
  return credentials.token

Java

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refresh();
  return googleCredentials.getAccessToken().getTokenValue();
}

Sau khi mã truy cập của bạn hết hạn, phương thức làm mới mã thông báo sẽ được gọi để tự động truy xuất mã truy cập đã cập nhật.

Để cấp quyền truy cập vào FCM, hãy yêu cầu cấp phạm vi https://www.googleapis.com/auth/firebase.messaging.

Cách thêm mã truy cập vào tiêu đề của yêu cầu HTTP:

Thêm mã thông báo dưới dạng giá trị của tiêu đề Authorization theo định dạng Authorization: Bearer <access_token>:

nút.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

Java

URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getServiceAccountAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

Cho phép yêu cầu gửi giao thức cũ

Với giao thức cũ HTTP, mỗi yêu cầu phải chứa khoá máy chủ từ Thẻ Nhắn tin qua đám mây trong phần Cài đặt bảng điều khiển của Firebase . Đối với XMPP, bạn phải sử dụng cùng một khoá máy chủ để thiết lập kết nối.

Di chuyển khoá máy chủ cũ

Kể từ tháng 3 năm 2020, FCM đã ngừng tạo khoá máy chủ cũ. Các khoá máy chủ cũ hiện có sẽ tiếp tục hoạt động, nhưng bạn nên thay vào đó, hãy sử dụng phiên bản mới hơn của khoá có nhãn Khoá máy chủ trong bảng điều khiển của Firebase.

Nếu muốn xoá khoá máy chủ cũ hiện có, bạn có thể thực hiện trong Bảng điều khiển Google Cloud.

Cho phép yêu cầu HTTP

Yêu cầu thông báo bao gồm hai phần: phần đầu HTTP và phần nội dung HTTP. Tiêu đề HTTP phải có các tiêu đề sau:

  • Authorization: key=YOUR_SERVER_KEY
    Hãy đảm bảo đây là khoá máy chủ. Khoá này có giá trị là có sẵn trong Thẻ Nhắn tin qua đám mây trong ngăn Cài đặt trên bảng điều khiển của Firebase. FCM từ chối các khoá của nền tảng Android, Apple và trình duyệt.
  • Content-Type: application/json cho JSON; application/x-www-form-urlencoded;charset=UTF-8 cho văn bản thuần tuý.
    Nếu bạn bỏ qua Content-Type, định dạng được giả định là văn bản thuần tuý.

Ví dụ:

Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
  "data" : {
    ...
  },
}

Xem Tạo yêu cầu gửi để biết toàn bộ thông tin chi tiết về cách tạo yêu cầu gửi. Tham chiếu giao thức HTTP cũ cung cấp danh sách tất cả các tham số có trong thông báo của bạn.

Kiểm tra tính hợp lệ của khoá máy chủ

Nếu bạn gặp lỗi xác thực khi gửi thư, hãy kiểm tra tính hợp lệ của khoá máy chủ của bạn. Ví dụ: trên Linux, hãy chạy lệnh sau:

api_key=YOUR_SERVER_KEY

curl --header "Authorization: key=$api_key" \
     --header Content-Type:"application/json" \
     https://fcm.googleapis.com/fcm/send \
     -d "{\"registration_ids\":[\"ABC\"]}"

Nếu bạn nhận được mã trạng thái HTTP 401, thì có nghĩa là Khoá máy chủ của bạn không hợp lệ.

Cho phép kết nối XMPP

Với XMPP, bạn có thể duy trì kết nối liên tục, không đồng bộ, hai chiều tới máy chủ FCM. Chiến lược phát hành đĩa đơn kết nối này có thể được dùng để gửi và nhận thông báo giữa máy chủ của bạn và của người dùng Thiết bị kết nối với FCM.

Bạn có thể sử dụng hầu hết Thư viện XMPP để quản lý kết nối lâu dài với FCM. Điểm cuối XMPP chạy lúc fcm-xmpp.googleapis.com:5235. Khi kiểm thử với người dùng không phải người dùng phát hành công khai, bạn nên kết nối với máy chủ tiền sản xuất tại fcm-xmpp.googleapis.com:5236 (hãy lưu ý cổng khác).

Thường xuyên kiểm thử trước khi phát hành công khai (một môi trường nhỏ hơn nơi các bản dựng FCM mới nhất chạy) giúp tách biệt người dùng thực khỏi mã kiểm thử. Kiểm thử thiết bị và mã kiểm thử kết nối với fcm-xmpp.googleapis.com:5236 nên sử dụng một mã nhận dạng người gửi FCM khác để tránh mọi rủi ro gửi thông báo kiểm thử cho người dùng phiên bản chính thức hoặc gửi thông báo ngược dòng từ lưu lượng truy cập thực tế qua kiểm tra kết nối.

Việc kết nối có hai yêu cầu quan trọng:

  • Bạn phải bắt đầu kết nối Bảo mật tầng truyền tải (TLS). Lưu ý rằng FCM hiện không hỗ trợ STARTtiện ích TLS.
  • FCM yêu cầu cơ chế xác thực SASL PLAIN sử dụng <your_FCM_Sender_Id>@fcm.googleapis.com (Mã người gửi FCM) và khoá máy chủ làm mật khẩu. Các giá trị này là có sẵn trong Thẻ Nhắn tin qua đám mây trong ngăn Cài đặt trên bảng điều khiển của Firebase.

Nếu không kết nối được tại bất kỳ thời điểm nào, bạn nên kết nối lại ngay lập tức. Không cần tắt sau khi ngắt kết nối diễn ra sau đó xác thực. Đối với mỗi mã người gửi, FCM cho phép kết nối song song 2500 kết nối.

Các đoạn mã sau đây minh hoạ cách thực hiện quy trình xác thực và cấp phép cho kết nối XMPP với FCM.

Máy chủ XMPP

Máy chủ XMPP yêu cầu kết nối đến FCM

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

FCM mở kết nối và yêu cầu một cơ chế xác thực, bao gồm PLAIN.

<stream:features>
  <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
    <mechanism>X-OAUTH2</mechanism>
    <mechanism>X-GOOGLE-TOKEN</mechanism>
    <mechanism>PLAIN</mechanism>
  </mechanisms>
</stream:features>

Máy chủ XMPP

Máy chủ XMPP phải phản hồi bằng cách sử dụng phương thức xác thực PLAIN, cung cấp khoá máy chủ từ Thẻ Nhắn tin qua đám mây trong ngăn Cài đặt trên bảng điều khiển của Firebase.

<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>

FCM

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

Máy chủ XMPP

<stream:stream to="fcm.googleapis.com"
        version="1.0" xmlns="jabber:client"
        xmlns:stream="http://etherx.jabber.org/streams">

FCM

<stream:features>
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
  <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</stream:features>

Máy chủ XMPP

<iq type="set">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"></bind>
</iq>

FCM

<iq type="result">
  <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
    <jid>SENDER_ID@fcm.googleapis.com/RESOURCE</jid>
  </bind>
</iq>

Lưu ý: FCM không sử dụng tài nguyên ràng buộc trong khi định tuyến thư.

Xem Tạo yêu cầu gửi để biết toàn bộ thông tin chi tiết về cách tạo yêu cầu gửi. Tài liệu tham khảo về giao thức XMPP cũ cung cấp danh sách tất cả các tham số có trong thông báo của bạn.