[英]How do I restrict Google App Engine Endpoints API access to only my Android applications?
我是一名Android開發人員,為我的應用構建了我的第一個Google App Engine(java)后端。 除了我的應用程序之外,我不希望任何其他人訪問此API。 (我計划在我的Android應用程序中使用App引擎驗證InApp購買)。 我的數據與用戶無關,因此我不希望用戶即使使用他們的Google帳戶(在網絡或Android設備上)登錄也能訪問我的API。
我按照“在API后端中指定授權客戶端”( https://developers.google.com/appengine/docs/java/endpoints/auth )中提到的步驟進行操作,例如生成客戶端ID並將其添加到@Api(clientIds和觀眾)除了“添加用戶參數” - 因為我不需要用戶身份驗證。
然后我部署了App引擎,我仍然可以通過API資源管理器訪問API( https://your_app_id.appspot.com/_ah/api/explorer )(我還沒有添加API_EXPLORER客戶端ID)
我在添加客戶端ID之前使用使用端點庫構建的APK進行了測試,並且仍然可以訪問API。
是否必須向所有端點API添加“用戶參數”? 實現我的目的(限制API到我的Android應用程序)。
我可以從Android客戶端傳遞null作為userAccount名稱並忽略服務器上的用戶參數值(因為它將為null)? 這是否確保API只能從我的Android應用程序訪問(因為客戶端ID是為我的包名和APK的SHA1生成的?)
我應該為此目的使用類似服務帳戶的東西嗎?
文檔說,對於Android,必須添加Android和Web客戶端ID,並且受眾必須與Web客戶端ID相同。 這是否可以訪問任何其他Web客戶端? 我可以跳過提及Web客戶端ID並仍然達到我的目的嗎?
感謝您的時間和幫助。
......隨着我的進一步調查而更新......
我做了以下事情:
在后端的API中添加了User參數 - 但沒有檢查空值。 無需傳遞任何憑據即可訪問API(來自Android調試APK和API資源管理器)
然后,我試過了
mCredential = GoogleAccountCredential.usingAudience(this,“server:client_id:”+ WEB_CLIENT_ID); mCredential.setSelectedAccountName(NULL);
並將此憑據傳遞給API構建器(如其他一些帖子中所建議的)導致致命異常。 所以,我們不能傳遞null帳戶名。
我可以在沒有OAuth的情況下使用API資源管理器調用API。 但是當我啟用OAuth時,它提示錯誤,說不允許此客戶端ID! (我還沒有在client_ids {}中添加com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID)
然后我添加了代碼,如果用戶為null,則在后端拋出OAuthRequestException。 這導致API資源管理器在沒有OAuth的情況下收到錯誤。 將API_EXPLORER_CLIENT_ID添加到client_ids后,它可以啟用OAuth
添加了從我的Android應用程序傳遞有效用戶帳戶名(電子郵件)的代碼。 然后,我只能使用我的發布APK訪問API。 即使是調試APK也有例外! - 這是我的預期。所以,我認為沒有其他Android應用程序能夠訪問此API。
因此,不檢查后端API上的null用戶是個壞主意(如其他帖子所示)。 它沒有提到任何client_ids而沒有User param。
我現在唯一的問題是:如果有人可以從APK中找出WEB_CLIENT_ID,他們是否可以使用它來構建一個Web客戶端來訪問我的API(我沒有在代碼中的任何地方提到過客戶端秘密。所以我認為這是不可能的)。
我確實搜索了Google群組和Stackoverflow,但目前尚不清楚。
(將我的“應用” 驗證到Google雲端點而不是“用戶”)將我的“應用”驗證為Google Cloud Endpoints而不是“用戶”
(如何保護使用Google Cloud Endpoints構建的API?) 如何保護使用Google Cloud Endpoints構建的API?
(限制訪問谷歌雲端點到Android應用) 限制訪問谷歌雲端點到Android應用程序
我有類似的問題,不是在Android和App Engine之間,而是在單獨的服務器和App Engine之間。 我處理它的方法是將簽名哈希字段作為參數添加到每個API調用。 如果請求有不正確的簽名,則會被拒絕。
例如,假設您的API端點是example.com/api/do_thing?param1=foo
。 我將散列整個url以及一個密鑰,然后將哈希的結果附加到請求: example.com/api/do_thing?param1=foo&hash=[some long hex value]
hash=[ example.com/api/do_thing?param1=foo&hash=[some long hex value]
。
然后,在服務器端,我首先從url請求中刪除哈希,然后對剩余的所有內容運行哈希。 最后,檢查計算的散列是否與隨請求一起發送的散列匹配,如果不匹配,則可以拒絕該請求。
但是,您的密鑰仍然保密,這一點非常重要。 您必須在Android上小心這一點,因為有人可能會嘗試反編譯您的APK。
面對同樣的問題比你! 在沒有Google用戶帳戶的情況下驗證Android端點是不可能的!
所以這是我解決這個問題的方法,沒有任何用戶交互(也許不是正確但有效,你有強大的身份驗證(SHA1 + Google帳戶)):
這是我的安卓代碼
獲取並構建有效憑據
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
使用此憑據進行安全呼叫
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
這是我的API后綴代碼: API注釋
@Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
方法代碼:
public Collection<Campagne> getCampagnes(@Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
目前,它只適用於Android(我不知道我們將如何做IOS ..)..
希望它會對你有所幫助!
Google提供了針對Android
, web
和iOS
執行此操作的方法。步驟包括:
這些步驟在Google的Using Auth with Endpoints和此博客上都有詳細的詳細說明
面對同樣的問題,這是我研究的結果:
但是:
如果我沒有向方法添加用戶參數:檢查有關Android應用程序客戶端ID不起作用
如果我添加USER參數但不要求用戶選擇其谷歌帳戶來創建憑證...也不起作用...
結論:似乎必須連接用戶帳戶以檢查要執行的應用程序客戶端ID ...我真的不明白為什么因為2個進程之間不存在鏈接
選擇您的項目,轉到憑證部分
創建一個新的api密鑰
創建一個新的Android密鑰
單擊“編輯允許的Android應用程序”並輸入您的SHA1密鑰; 你的android包名
如果這解決了問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.