簡體   English   中英

如何限制Google App Engine端點API只能訪問我的Android應用程序?

[英]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,但目前尚不清楚。

我有類似的問題,不是在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提供了針對AndroidwebiOS執行此操作的方法。步驟包括:

  1. 為要允許向API發出請求的應用指定客戶端ID
  2. 將User參數添加到要受授權保護的所有公開方法。
  3. 為任何Android客戶端再次生成客戶端庫
  4. 重新部署后端API。
  5. 將重新生成的jar文件更新為Android客戶端的Android項目。

這些步驟在Google的Using Auth with Endpoints和此博客都有詳細的詳細說明

面對同樣的問題,這是我研究的結果:

  • 在Google控制台中添加了帶有SHA1指紋的Android cliend id
  • 在API注釋中使用它

但是:

  • 如果我沒有向方法添加用戶參數:檢查有關Android應用程序客戶端ID不起作用

  • 如果我添加USER參數但不要求用戶選擇其谷歌帳戶來創建憑證...也不起作用...

結論:似乎必須連接用戶帳戶以檢查要執行的應用程序客戶端ID ...我真的不明白為什么因為2個進程之間不存在鏈接

訪問此站點

選擇您的項目,轉到憑證部分

創建一個新的api密鑰

創建一個新的Android密鑰

單擊“編輯允許的Android應用程序”並輸入您的SHA1密鑰; 你的android包名

如果這解決了問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM