共用方式為


將驗證新增至 Android 應用程式

總結

在本教學課程中,您會使用支持的識別提供者,將驗證新增至Android上的todolist快速入門專案。 本教學課程是以 開始使用Mobile Apps 教學課程為基礎,您必須先完成此教學課程。

註冊您的應用程式以進行驗證並設定 Azure App Service

首先,您必須在身分提供者的網站註冊您的應用程式,然後在行動應用程式的後端設定提供者產生的認證。

  1. 按照提供商的特定指示來設定您的首選身分驗證提供者:

  2. 針對您想要在應用程式中支援的每個提供者重複上述步驟。

將您的應用程式新增至允許的外部重新導向URL

安全驗證需要您為應用程式定義新的 URL 配置。 這可讓驗證系統在驗證程式完成之後重新導向回您的應用程式。 在本教學課程中,我們會在整個過程中使用 URL scheme appname。 不過,您可以使用您選擇的任何 URL 配置。 它應該是您的行動應用程式所特有的。 若要在伺服器端開啟重新導向:

  1. Azure 入口網站中,選取您的 App Service(應用服務)。

  2. 按一下 [驗證/授權] 選單選項。

  3. 在 [允許的外部重新導向 URL中,輸入 appname://easyauth.callback。 此字串中的 appname 是行動應用程式的 URL 配置。 它應該遵循通訊協定的一般 URL 規格(只使用字母和數位,並以字母開頭)。 您應該記下您選擇的字串,因為您需要在數個地方使用URL配置來調整行動應用程式程式代碼。

  4. 按一下 [確定]。

  5. 點選 [儲存]。

限制已驗證用戶的許可權

根據預設,Mobile Apps 後端中的 API 可以匿名叫用。 接下來,您必須限制僅對已驗證用戶端的存取。

  • Node.js 後端 (透過 Azure 入口網站)

    在Mobile Apps 設定中,按兩下 [[簡易數據表],然後選取您的數據表。 按一下 [變更許可權],針對所有許可權選取 [僅限已驗證存取 ],然後按一下 [儲存]。

  • .NET 後端 (C#)

    在伺服器專案中,流覽至 Controllers>TodoItemController.cs。 將 [Authorize] 屬性新增至 TodoItemController 類別,如下所示。 若要只限制對特定方法的存取,您也可以只將此屬性套用至那些方法,而不是類別。 重新發佈伺服器專案。

      [Authorize]
      public class TodoItemController : TableController<TodoItem>
    
  • Node.js 後端(透過 Node.js 程式代碼)

    若要要求驗證資料表存取,請將下列這一行新增至 Node.js 伺服器腳本:

      table.access = 'authenticated';
    

    如需詳細資訊,請參閱 如何:要求驗證才能存取數據表。 若要瞭解如何從您的網站下載快速入門程式代碼專案,請參閱 如何:使用 Git下載 Node.js 後端快速入門程式代碼專案。

  • 在 Android Studio 中,開啟您使用 開始使用 Mobile Apps 教學課程完成的專案。 從 [ 執行 ] 功能表中,按兩下 [ 執行應用程式],並確認在應用程式啟動時引發狀態代碼為 401(未經授權)的未處理例外狀況。

    發生此例外狀況的原因是應用程式嘗試以未經驗證的使用者身分存取後端,但 TodoItem 資料表現在需要驗證。

接下來,您會更新應用程式來驗證使用者,再向Mobile Apps 後端要求資源。

將驗證新增至應用程式

  1. 在 Android Studio 中開啟專案。

  2. 在 Android Studio 的 [專案總 管] 中,開啟 ToDoActivity.java 檔案並新增下列匯入語句:

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceAuthenticationProvider;
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceUser;
    
  3. 將下列方法新增至 ToDoActivity 類別:

    // You can choose any unique number here to differentiate auth providers from each other. Note this is the same code at login() and onActivityResult().
    public static final int GOOGLE_LOGIN_REQUEST_CODE = 1;
    
    private void authenticate() {
        // Sign in using the Google provider.
        mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the login request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    

    此程式代碼會建立方法來處理Google驗證程式。 對話框會顯示已驗證使用者的識別碼。 您只能在身份驗證成功後繼續。

    備註

    如果您使用Google以外的識別提供者,請將傳遞至 登入 方法的值變更為下列其中一個值: MicrosoftAccountFacebookTwitterwindowsazureactivedirectory

  4. onCreate 方法中,於具現化 MobileServiceClient 物件的程式代碼後面新增下列程式代碼行。

    authenticate();
    

    此呼叫會啟動驗證程式。

  5. authenticate(); 方法中之後的其餘程式碼移至新的 createTable 方法:

    private void createTable() {
    
        // Get the table instance to use.
        mToDoTable = mClient.getTable(ToDoItem.class);
    
        mTextNewToDo = (EditText) findViewById(R.id.textNewToDo);
    
        // Create an adapter to bind the items with the view.
        mAdapter = new ToDoItemAdapter(this, R.layout.row_list_to_do);
        ListView listViewToDo = (ListView) findViewById(R.id.listViewToDo);
        listViewToDo.setAdapter(mAdapter);
    
        // Load the items from Azure.
        refreshItemsFromTable();
    }
    
  6. 若要確保重新導向如預期般運作,請將 下列 代碼段 RedirectUrlActivity 新增至 AndroidManifest.xml

    <activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="{url_scheme_of_your_app}"
                android:host="easyauth.callback"/>
        </intent-filter>
    </activity>
    
  7. redirectUriScheme 新增至你的Android應用程式中。

    android {
        buildTypes {
            release {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
            debug {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
        }
    }
    
  8. com.android.support:customtabs:23.0.1 新增至 build.gradle 的相依性:

    dependencies {
        // ...
        compile 'com.android.support:customtabs:23.0.1'
    }
    
  9. 從 [ 執行 ] 功能表中,按兩下 [ 執行應用程式 ] 以啟動應用程式,並使用您選擇的識別提供者登入。

警告

提及的 URL 格式會區分大小寫。 請確定所有出現的 {url_scheme_of_you_app} 都使用相同的大小寫。

成功登入時,應用程式應該會執行而不會發生錯誤,而且您應該能夠查詢後端服務並更新數據。

用戶端快取驗證令牌

上一個範例顯示標準登入,這需要用戶端在每次應用程式啟動時連絡識別提供者和後端 Azure 服務。 此方法效率不佳,如果許多客戶嘗試同時啟動您的應用程式,您就可能會發生使用量相關問題。 更好的方法是快取 Azure 服務傳回的授權令牌,並在使用提供者型登入之前先嘗試使用此令牌。

備註

不論您是使用用戶端管理還是服務管理的驗證,您都可以快取後端 Azure 服務所發出的令牌。 本教程使用由服務管理的身份驗證。

  1. 開啟ToDoActivity.java檔案,並新增下列匯入語句:

    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
  2. 將下列成員新增至 類別 ToDoActivity

    public static final String SHAREDPREFFILE = "temp";
    public static final String USERIDPREF = "uid";
    public static final String TOKENPREF = "tkn";
    
  3. 在 ToDoActivity.java 檔案中,為方法新增下列定義 cacheUserToken

    private void cacheUserToken(MobileServiceUser user)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString(USERIDPREF, user.getUserId());
        editor.putString(TOKENPREF, user.getAuthenticationToken());
        editor.commit();
    }
    

    這個方法會將使用者標識碼和令牌儲存在標示為私用的喜好設定檔中。 這應該能夠保護快取的存取,以確保裝置上的其他應用程式不能存取令牌。 應用程式的喜好設定已沙盒化。 不過,如果有人取得裝置存取權,他們可能會以其他方式取得令牌快取的存取權。

    備註

    如果數據的令牌存取被視為高度敏感,且有人可能會取得裝置的存取權,您可以進一步使用加密來保護令牌。 不過,完全安全的解決方案已超出本教學課程的範圍,而且取決於您的安全性需求。

  4. 在 ToDoActivity.java 檔案中,為方法新增下列定義 loadUserTokenCache

    private boolean loadUserTokenCache(MobileServiceClient client)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        String userId = prefs.getString(USERIDPREF, null);
        if (userId == null)
            return false;
        String token = prefs.getString(TOKENPREF, null);
        if (token == null)
            return false;
    
        MobileServiceUser user = new MobileServiceUser(userId);
        user.setAuthenticationToken(token);
        client.setCurrentUser(user);
    
        return true;
    }
    
  5. ToDoActivity.java 檔案中,將 authenticateonActivityResult 方法替換為下列使用令牌快取的方法。 如果您想要使用Google以外的帳戶,請變更登入提供者。

    private void authenticate() {
        // We first try to load a token cache if one exists.
        if (loadUserTokenCache(mClient))
        {
            createTable();
        }
        // If we failed to load a token cache, sign in and create a token cache
        else
        {
            // Sign in using the Google provider.
            mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the sign-in request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    cacheUserToken(mClient.getCurrentUser());
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    
  6. 使用有效的帳戶建置應用程式和測試驗證。 至少執行兩次。 在第一次執行期間,您應能看到登入並建立令牌快取的提示。 之後,每次執行都會嘗試載入令牌快取以進行驗證。 您不應該需要登入。

後續步驟

既然您已完成此基本身份驗證教學課程,請考慮繼續進行下列其中一個教學課程: