Share via


將驗證加入 Android 應用程式中

總結

在本教學課程中,您可以使用支援的身分識別提供者,將驗證加入 Android 上的 TodoList 快速入門專案。 本教學課程以開始使用 Mobile Apps 為基礎,您必須先完成該教學課程。

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

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

  1. 依照提供者特定的指示設定您偏好的身分識別提供者:

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

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

安全的驗證會要求您為應用程式定義新的 URL 配置。 這讓驗證系統能夠在驗證程序完成之後,重新導向回到您的應用程式。 我們會在這整個教學課程中使用 URL 配置 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#)

    在伺服器專案中,流覽至控制器>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 陳述式:

    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,請將傳給 login 方法的值變更為下列其中一個值:MicrosoftAccountFacebookTwitterwindowsazureactivedirectory

  4. OnCreateMobileServiceClient 方法中,在具現化 物件的程式碼後面加入下列這一行程式碼。

    authenticate();
    

    此呼叫會啟動驗證程序。

  5. >oncreate方法中的其餘程式碼 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 應用程式的 build.gradle

    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 陳述式:

    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. 使用有效的帳戶建置應用程式,並且測試驗證。 至少執行 2 次此動作。 第一次執行時,您應該會收到提示,要求您登入並建立權杖快取。 之後,每次執行會嘗試載入權杖快取來進行驗證。 您應該不需要登入。

後續步驟

現在您已經完成了這個基本驗證的教學課程,可以考慮繼續進行下列其中一個教學課程: