Consumer SDK 會使用 JSON Web Token 提供授權。JSON Web Token (JWT) 是授權權杖,可提供一或多項服務聲明。
Consumer SDK 會使用應用程式提供的 JSON Web Token 與 Fleet Engine 通訊。如要進一步瞭解車隊引擎伺服器所需的權杖,請參閱「JSON Web 權杖」和「發出 JSON Web 權杖」。
授權權杖可提供下列 Fleet Engine 服務的存取權:
TripService
- 讓 Consumer SDK 存取行程詳細資料,包括車輛位置、路線和預估到達時間。行程服務的授權權杖必須在權杖的authorization
標頭中加入tripid:TRIP_ID
要求,其中TRIP_ID
是共享的隨選行程 ID。VehicleService
- 提供 Consumer SDK 關於車輛大致位置的資訊,以便顯示車輛密度圖層和預估上車點預估抵達時間。由於 Consumer SDK 只使用大略位置,因此車輛服務的授權權杖不需要vehicleid
權杖。
什麼是符記?
Fleet Engine 要求使用 JSON Web Token (JWT) 來呼叫來自信任程度較低的環境 (智慧型手機和瀏覽器) 的 API 方法。
JWT 會在您的伺服器上產生,並經過簽署和加密,然後傳遞至用戶端,以便在後續的伺服器互動中使用,直到過期或不再有效為止。
重要詳細資料
- 使用應用程式預設憑證驗證並授權 Fleet Engine。
- 使用適當的服務帳戶簽署 JWT。請參閱Fleet Engine 基本資訊中的Fleet Engine 服務帳戶角色。
如要進一步瞭解 JSON Web Token,請參閱 Fleet Engine 重點中的「JSON Web Token」。
用戶端如何取得權杖?
駕駛員或消費者使用適當的授權憑證登入應用程式後,從該裝置發出的任何更新都必須使用適當的授權權杖,以便向 Fleet Engine 傳達應用程式的權限。
身為開發人員,您的用戶端實作項目應提供以下功能:
- 從伺服器擷取 JSON Web Token。
- 在權杖到期前重複使用,盡量減少權杖重新整理次數。
- 在權杖到期時重新整理。
AuthTokenFactory
類別會在位置更新時產生授權權杖。SDK 必須將符記與更新資訊封裝,才能傳送至 Fleet Engine。請務必在初始化 SDK 之前,確認伺服器端實作項目可以發出權杖。
如要進一步瞭解 Fleet Engine 服務所需的權杖,請參閱 Fleet Engine 的「發出 JSON Web 權杖」一文。
授權權杖擷取器範例
以下程式碼範例示範如何實作授權權杖回呼。
Java
class JsonAuthTokenFactory implements AuthTokenFactory {
private static final String TOKEN_URL =
"https://yourauthserver.example/token";
private static class CachedToken {
String tokenValue;
long expiryTimeMs;
String tripId;
}
private CachedToken token;
/*
* This method is called on a background thread. Blocking is OK. However, be
* aware that no information can be obtained from Fleet Engine until this
* method returns.
*/
@Override
public String getToken(AuthTokenContext context) {
// If there is no existing token or token has expired, go get a new one.
String tripId = context.getTripId();
if (tripId == null) {
throw new RuntimeException("Trip ID is missing from AuthTokenContext");
}
if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
!tripId.equals(token.tripId)) {
token = fetchNewToken(tripId);
}
return token.tokenValue;
}
private static CachedToken fetchNewToken(String tripId) {
String url = TOKEN_URL + "/" + tripId;
CachedToken token = new CachedToken();
try (Reader r = new InputStreamReader(new URL(url).openStream())) {
com.google.gson.JsonObject obj
= com.google.gson.JsonParser.parseReader(r).getAsJsonObject();
token.tokenValue = obj.get("ServiceToken").getAsString();
token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong();
/*
* The expiry time could be an hour from now, but just to try and avoid
* passing expired tokens, we subtract 5 minutes from that time.
*/
token.expiryTimeMs -= 5 * 60 * 1000;
} catch (IOException e) {
/*
* It's OK to throw exceptions here. The error listeners will receive the
* error thrown here.
*/
throw new RuntimeException("Could not get auth token", e);
}
token.tripId = tripId;
return token;
}
}
Kotlin
class JsonAuthTokenFactory : AuthTokenFactory() {
private var token: CachedToken? = null
/*
* This method is called on a background thread. Blocking is OK. However, be
* aware that no information can be obtained from Fleet Engine until this
* method returns.
*/
override fun getToken(context: AuthTokenContext): String {
// If there is no existing token or token has expired, go get a new one.
val tripId =
context.getTripId() ?:
throw RuntimeException("Trip ID is missing from AuthTokenContext")
if (token == null || System.currentTimeMillis() > token.expiryTimeMs ||
tripId != token.tripId) {
token = fetchNewToken(tripId)
}
return token.tokenValue
}
class CachedToken(
var tokenValue: String? = "",
var expiryTimeMs: Long = 0,
var tripId: String? = "",
)
private companion object {
const val TOKEN_URL = "https://yourauthserver.example/token"
fun fetchNewToken(tripId: String) {
val url = "$TOKEN_URL/$tripId"
val token = CachedToken()
try {
val reader = InputStreamReader(URL(url).openStream())
reader.use {
val obj = com.google.gson.JsonParser.parseReader(r).getAsJsonObject()
token.tokenValue = obj.get("ServiceToken").getAsString()
token.expiryTimeMs = obj.get("TokenExpiryMs").getAsLong()
/*
* The expiry time could be an hour from now, but just to try and avoid
* passing expired tokens, we subtract 5 minutes from that time.
*/
token.expiryTimeMs -= 5 * 60 * 1000
}
} catch (e: IOException) {
/*
* It's OK to throw exceptions here. The error listeners will receive the
* error thrown here.
*/
throw RuntimeException("Could not get auth token", e)
}
token.tripId = tripId
return token
}
}
}