HS256 chỉ được sử dụng nếu bạn sử dụng mật khẩu để ký mã thông báo. Firebase sử dụng RS256 khi phát hành mã thông báo, do đó, bạn cần các khóa công khai từ URL đã cho và bạn cần đặt thuật toán thành RS256.
Cũng lưu ý rằng các dấu hiệu bạn nhận được trong ứng dụng của bạn không phải là một mảng mà là một chuỗi ký tự có 3 phần: header
, body
, và signature
. Mỗi phần được phân tách bằng dấu a .
, do đó nó cung cấp cho bạn một chuỗi đơn giản:header.body.signature
Những gì bạn
cần làm để xác minh mã thông báo là tải xuống các khóa công khai thường xuyên từ URL đã cho [kiểm tra Cache-Control
tiêu đề để biết thông tin đó] và lưu nó [JSON] trong một tệp, vì vậy bạn sẽ không phải truy xuất nó mỗi lần. thời gian bạn cần kiểm tra JWT. Sau đó, bạn có thể đọc trong tệp và giải mã JSON. Đối tượng được giải mã có thể được chuyển cho JWT::decode[...]
hàm. Đây là một mẫu ngắn:
$pkeys_raw = file_get_contents["cached_public_keys.json"];
$pkeys = json_decode[$pkeys_raw, true];
$decoded = JWT::decode[$token, $pkeys, ["RS256"]];
Bây giờ $decoded
biến chứa trọng tải của mã thông báo. Khi bạn có đối tượng được giải mã, bạn vẫn cần xác
minh nó. Theo hướng dẫn về xác minh mã thông báo ID, bạn phải kiểm tra những điều sau:
exp
là trong tương laiiat
là trong quá khứiss
://securetoken.google.com/
aud
:sub
không trống
Vì vậy, ví dụ: bạn có thể kiểm tra iss
như sau [ FIREBASE_APP_ID
ID ứng dụng từ bảng điều khiển firebase ở đâu]:
$iss_is_valid = isset[$decoded->iss] && $decoded->iss === "//securetoken.google.com/" . FIREBASE_APP_ID;
Đây là một mẫu hoàn chỉnh để làm mới các phím và truy xuất chúng.
Tuyên bố từ chối trách nhiệm: Tôi chưa thử nghiệm nó và điều này về cơ bản chỉ dành cho mục đích thông tin.
$keys_file = "securetoken.json"; // the file for the downloaded public keys
$cache_file = "pkeys.cache"; // this file contains the next time the system has to revalidate the keys
/**
* Checks whether new keys should be downloaded, and retrieves them, if needed.
*/
function checkKeys[]
{
if [file_exists[$cache_file]] {
$fp = fopen[$cache_file, "r+"];
if [flock[$fp, LOCK_SH]] {
$contents = fread[$fp, filesize[$cache_file]];
if [$contents > time[]] {
flock[$fp, LOCK_UN];
} elseif [flock[$fp, LOCK_EX]] { // upgrading the lock to exclusive [write]
// here we need to revalidate since another process could've got to the LOCK_EX part before this
if [fread[$fp, filesize[$this->cache_file]] refreshKeys[$fp];
}
flock[$fp, LOCK_UN];
} else {
throw new \RuntimeException['Cannot refresh keys: file lock upgrade error.'];
}
} else {
// you need to handle this by signaling error
throw new \RuntimeException['Cannot refresh keys: file lock error.'];
}
fclose[$fp];
} else {
refreshKeys[];
}
}
/**
* Downloads the public keys and writes them in a file. This also sets the new cache revalidation time.
* @param null $fp the file pointer of the cache time file
*/
function refreshKeys[$fp = null]
{
$ch = curl_init[];
curl_setopt[$ch, CURLOPT_URL, "//www.googleapis.com/robot/v1/metadata/x509/"];
curl_setopt[$ch, CURLOPT_RETURNTRANSFER, 1];
curl_setopt[$ch, CURLOPT_HEADER, 1];
$data = curl_exec[$ch];
$header_size = curl_getinfo[$ch, CURLINFO_HEADER_SIZE];
$headers = trim[substr[$data, 0, $header_size]];
$raw_keys = trim[substr[$data, $header_size]];
if [preg_match['/age:[ ]+?[\d+]/i', $headers, $age_matches] === 1] {
$age = $age_matches[1];
if [preg_match['/cache-control:.+?max-age=[\d+]/i', $headers, $max_age_matches] === 1] {
$valid_for = $max_age_matches[1] - $age;
ftruncate[$fp, 0];
fwrite[$fp, "" . [time[] + $valid_for]];
fflush[$fp];
// $fp will be closed outside, we don't have to
$fp_keys = fopen[$keys_file, "w"];
if [flock[$fp_keys, LOCK_EX]] {
fwrite[$fp_keys, $raw_keys];
fflush[$fp_keys];
flock[$fp_keys, LOCK_UN];
}
fclose[$fp_keys];
}
}
}
/**
* Retrieves the downloaded keys.
* This should be called anytime you need the keys [i.e. for decoding / verification].
* @return null|string
*/
function getKeys[]
{
$fp = fopen[$keys_file, "r"];
$keys = null;
if [flock[$fp, LOCK_SH]] {
$keys = fread[$fp, filesize[$keys_file]];
flock[$fp, LOCK_UN];
}
fclose[$fp];
return $keys;
}
Điều tốt nhất là lên lịch cho một cronjob để gọi checkKeys[]
bất cứ khi nào cần, nhưng tôi không biết liệu nhà cung cấp của bạn có cho phép điều đó hay không. Thay vì điều đó, bạn có thể thực hiện việc này cho mọi yêu cầu:
checkKeys[];
$pkeys_raw = getKeys[]; // check if $raw_keys is not null before using it!
27 hữu ích 5 bình luận chia sẻ