共用方式為


驗證和授權

注意

本電子書於 2017 年春季出版,此後尚未更新。 這本書中有很多仍然有價值的,但一些材料已經過時。

驗證是從使用者取得識別認證的程式,例如使用者的名稱和密碼,以及針對授權單位驗證這些認證。 如果認證有效,提交認證的實體會被視為已驗證的身分識別。 一旦驗證身分識別之後,授權程式會判斷該身分識別是否具有指定資源的存取權。

將驗證和授權 Xamarin.Forms 整合到與 ASP.NET MVC Web 應用程式通訊的應用程式有許多方法,包括使用 ASP.NET Core Identity、Microsoft、Google、Facebook 或 Twitter 等外部驗證提供者,以及驗證中間件。 eShopOnContainers 行動應用程式會使用 IdentityServer 4 的容器化身分識別微服務來執行驗證和授權。 行動應用程式會向IdentityServer 要求安全性令牌,以驗證使用者或存取資源。 若要讓 IdentityServer 代表用戶發行令牌,用戶必須登入 IdentityServer。 不過,IdentityServer 不提供使用者介面或資料庫以供驗證。 因此,在 eShopOnContainers 參考應用程式中,ASP.NET Core 身分識別即作此用。

驗證

當應用程式需要知道目前使用者的身分識別時,需要驗證。 ASP.NET Core 識別使用者的主要機制是 ASP.NET Core 身分識別成員資格系統,其會將使用者資訊儲存在開發人員所設定的資料存放區中。 一般而言,此數據存放區會是 EntityFramework 存放區,不過自定義存放區或第三方套件可用來將身分識別資訊儲存在 Azure 記憶體、Azure Cosmos DB 或其他位置。

針對使用本機用戶資料存放區的驗證案例,以及透過Cookie在要求之間保存身分識別資訊(如同在MVC Web 應用程式 ASP.NET 一般),ASP.NET Core Identity 是適合的解決方案。 不過,Cookie 不一定是保存及傳輸資料的自然方式。 例如,公開從行動應用程式存取的 RESTful 端點的 ASP.NET Core Web 應用程式通常需要使用持有人令牌驗證,因為無法在此案例中使用 Cookie。 不過,持有人令牌可以輕鬆地擷取並包含在從行動應用程式提出之 Web 要求的授權標頭中。

使用 IdentityServer 4 發出持有人令牌

IdentityServer 4 是 開放原始碼 OpenID 連線 和適用於 ASP.NET Core 的 OAuth 2.0 架構,可用於許多驗證和授權案例,包括發行本機 ASP.NET 核心身分識別使用者的安全性令牌。

注意

OpenID Connect 和 OAuth 2.0 非常類似,但職責不同。

OpenID Connect 是 OAuth 2.0 通訊協定最上層的驗證層。 OAuth 2 是一種通訊協定,可讓應用程式向安全性權杖服務要求存取權杖,並使用它們與 API 通訊。 這種委派可減少用戶端應用程式和 API 的複雜性,因為驗證和授權可以集中化。

OpenID 連線 和 OAuth 2.0 的組合結合了驗證和 API 存取的兩個基本安全性考慮,而 IdentityServer 4 則是這些通訊協定的實作。

在使用直接用戶端對微服務通訊的應用程式中,例如 eShopOnContainers 參考應用程式,可作為安全性令牌服務 (STS) 的專用驗證微服務可用來驗證使用者,如圖 9-1 所示。 如需直接用戶端對微服務通訊的詳細資訊,請參閱 用戶端與微服務之間的通訊。

Authentication by a dedicated authentication microservice

圖 9-1: 專用驗證微服務的驗證

eShopOnContainers 行動應用程式會與身分識別微服務通訊,其會使用 IdentityServer 4 來執行 API 的驗證和訪問控制。 因此,行動應用程式會向IdentityServer要求令牌,以驗證使用者或存取資源:

  • 向 IdentityServer 驗證使用者是透過要求 身分識別 令牌的行動應用程式達成,這代表驗證程序的結果。 至少會包含使用者的識別碼,以及用戶驗證方式和時間的相關信息。 它也可以包含其他身分識別數據。
  • 使用 IdentityServer 存取資源,可透過要求 存取 令牌的行動應用程式來達成,以允許存取 API 資源。 用戶端會要求存取權杖,並將其轉送至 API。 存取令牌包含客戶端和使用者的相關信息(如果有的話)。 然後,API 會使用該資訊授權,准許存取其資料。

注意

客戶端必須先向 IdentityServer 註冊,才能要求令牌。

將 IdentityServer 新增至 Web 應用程式

為了讓 ASP.NET Core Web 應用程式使用 IdentityServer 4,後者必須新增至 Web 應用程式的 Visual Studio 解決方案。 如需詳細資訊,請參閱 IdentityServer 檔中的概觀

一旦 IdentityServer 包含在 Web 應用程式的 Visual Studio 解決方案中,就必須將它新增至 Web 應用程式的 HTTP 要求處理管線,以便提供 OpenID 連線 和 OAuth 2.0 端點的要求。 這可在 Web 應用程式之 Startup 類別的 Configure 方法中達成,如下列程式碼範例所示:

public void Configure(  
    IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)  
{  
    ...  
    app.UseIdentity();  
    ...  
}

Web 應用程式之 HTTP 要求處理管線中的順序至關重要。 因此,IdentityServer 新增至管線的順序,必須在實作登入畫面的 UI 架構之前。

設定 IdentityServer

IdentityServer 應該ConfigureServices藉由呼叫 services.AddIdentityServer 方法,在 Web 應用程式的 Startup 類別中設定 IdentityServer,如 eShopOnContainers 參考應用程式的下列程式代碼範例所示:

public void ConfigureServices(IServiceCollection services)  
{  
    ...  
    services.AddIdentityServer(x => x.IssuerUri = "null")  
        .AddSigningCredential(Certificate.Get())                 
        .AddAspNetIdentity<ApplicationUser>()  
        .AddConfigurationStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .AddOperationalStore(builder =>  
            builder.UseSqlServer(connectionString, options =>  
                options.MigrationsAssembly(migrationsAssembly)))  
        .Services.AddTransient<IProfileService, ProfileService>();  
}

呼叫 services.AddIdentityServer 方法之後,還會呼叫其他 Fluent API 來設定下列項目:

  • 用於登入的認證。
  • 使用者可能要求存取的 API 和身分識別資源。
  • 要連線要求權杖的用戶端。
  • ASP.NET Core 身分識別。

提示

動態載入 IdentityServer 4 組態。 IdentityServer 4 的 API 允許從記憶體內的組態物件清單中設定 IdentityServer。 在 eShopOnContainers 參考應用程式中,這些記憶體內集合會硬式編碼到應用程式中。 不過,在生產案例中,其可以從組態檔或資料庫動態載入。

如需將 IdentityServer 設定為使用 ASP.NET Core 身分識別的相關資訊,請參閱 IdentityServer 文件中的使用 ASP.NET Core 身分識別

設定 API 資源

設定 API 資源時,AddInMemoryApiResources 方法預期有 IEnumerable<ApiResource> 集合。 下列程式碼範例示範的 GetApis 方法,會在 eShopOnContainers 參考應用程式中提供此集合:

public static IEnumerable<ApiResource> GetApis()  
{  
    return new List<ApiResource>  
    {  
        new ApiResource("orders", "Orders Service"),  
        new ApiResource("basket", "Basket Service")  
    };  
}

這個方法指定 IdentityServer 應該保護訂單和購物籃 API。 因此,對這些 API 進行呼叫時,需要 IdentityServer 受控存取令牌。 如需 ApiResource 類型的詳細資訊,請參閱 IdentityServer 4 文件中的 API 資源

設定身分識別資源

設定身分識別資源時,AddInMemoryIdentityResources 方法預期有 IEnumerable<IdentityResource> 集合。 身分識別資源是使用者識別碼、名稱或電子郵件地址等資料。 每個身分識別資源都有唯一的名稱,而且可以將任意宣告類型指派給它,然後包含在使用者的身分識別令牌中。 下列程式碼範例示範的 GetResources 方法,會在 eShopOnContainers 參考應用程式中提供此集合:

public static IEnumerable<IdentityResource> GetResources()  
{  
    return new List<IdentityResource>  
    {  
        new IdentityResources.OpenId(),  
        new IdentityResources.Profile()  
    };  
}

OpenID Connect 規格會指定一些標準身分識別資源。 最低需求是支援發出使用者的唯一識別碼。 公開 IdentityResources.OpenId 身分識別資源即可達成此目的。

注意

類別IdentityResources支援 OpenID 連線 規格中定義的所有範圍(openid、電子郵件、配置檔、電話和位址)。

IdentityServer 也支援定義自訂的身分識別資源。 如需類型的詳細資訊 IdentityResource ,請參閱 IdentityServer 4 檔中的身分識別資源

設定用戶端 \(英文\)

用戶端是可向 IdentityServer 要求權杖的應用程式。 一般而言,每個用戶端至少都必須定義下列設定:

  • 唯一的用戶端識別碼。
  • 允許與權杖服務的互動 (稱為授與類型)。
  • 身分識別和存取權杖傳送目的地位置 (稱為重新導向 URI)。
  • 允許用戶端存取的資源清單 (稱為範圍)。

設定用戶端時,AddInMemoryClients 方法預期有 IEnumerable<Client> 集合。 下列程式代碼範例示範在 eShopOnContainers 參考應用程式中提供此集合之 方法中 GetClients eShopOnContainers 行動應用程式的組態:

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
    return new List<Client>
    {
        ...
        new Client
        {
            ClientId = "xamarin",
            ClientName = "eShop Xamarin OpenId Client",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { clientsUrl["Xamarin"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{clientsUrl["Xamarin"]}/Account/Redirecting" },
            AllowedCorsOrigins = { "http://eshopxamarin" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket"
            },
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true
        },
        ...
    };
}

此組態會指定下列屬性的資料:

  • ClientId:用戶端的唯一標識符。
  • ClientName:用於記錄和同意畫面的客戶端顯示名稱。
  • AllowedGrantTypes:指定用戶端想要如何與 IdentityServer 互動。 如需詳細資訊,請參閱 設定驗證流程
  • ClientSecrets:指定從令牌端點要求令牌時所使用的用戶端密碼認證。
  • RedirectUris:指定要傳回令牌或授權碼的允許 URI。
  • RequireConsent:指定是否需要同意畫面。
  • RequirePkce:指定使用授權碼的用戶端是否必須傳送證明金鑰。
  • PostLogoutRedirectUris:指定允許的 URI 在註銷後重新導向至 。
  • AllowedCorsOrigins:指定用戶端的來源,讓 IdentityServer 能夠允許來自來源的跨原始來源呼叫。
  • AllowedScopes:指定用戶端可存取的資源。 用戶端預設無權存取任何資源。
  • AllowOfflineAccess:指定用戶端是否可以要求重新整理令牌。

設定驗證流程

用戶端與 IdentityServer 之間的驗證流程可透過在 Client.AllowedGrantTypes 屬性中指定授與類型來設定。 OpenID 連線 和 OAuth 2.0 規格會定義一些驗證流程,包括:

  • 隱 式。 此流程已針對瀏覽器型應用程式最佳化,應僅限使用者驗證之用,或要求驗證和存取權杖之用。 所有權杖都會透過瀏覽器傳輸,因此不允許重新整理權杖等進階功能。
  • 授權碼。 此流程可讓您在後端通道擷取權杖,而不是瀏覽器前端通道,同時還支援用戶端驗證。
  • 混合式。 此流程是隱含和授權碼授與類型的組合。 身分識別令牌會透過瀏覽器通道傳輸,並包含已簽署的通訊協議回應,以及其他成品,例如授權碼。 成功驗證回應之後,應該使用後端通道來擷取存取權和重新整理令牌。

提示

使用混合式驗證流程。 混合式驗證流程可減輕對瀏覽器通道的大量攻擊,而且是適合想要擷取存取權杖 (且可能是重新整理權杖) 之原生應用程式的建議流程。

如需驗證流程的詳細資訊,請參閱 IdentityServer 4 文件中的授與類型

執行驗證

若要讓 IdentityServer 代表用戶發行令牌,用戶必須登入 IdentityServer。 不過,IdentityServer 不提供使用者介面或資料庫以供驗證。 因此,在 eShopOnContainers 參考應用程式中,ASP.NET Core 身分識別即作此用。

eShopOnContainers 行動應用程式會使用混合式驗證流程向 IdentityServer 進行驗證,如圖 9-2 所示。

High-level overview of the sign-in process

圖 9-2: 登入程式的高階概觀

對提出 <base endpoint>:5105/connect/authorize登入要求。 成功驗證之後,IdentityServer 會傳回包含授權碼和身分識別權杖的驗證回應。 授權碼接著會傳送至 <base endpoint>:5105/connect/token,以存取、身分識別和重新整理令牌回應。

eShopOnContainers 行動應用程式會使用其他參數將要求傳送至 <base endpoint>:5105/connect/endsession來註銷 IdentityServer。 註銷之後,IdentityServer 會藉由將註銷後重新導向 URI 傳送回行動應用程式來回應。 圖 9-3 說明此程式。

High-level overview of the sign-out process

圖 9-3: 註銷程式的高層級概觀

在 eShopOnContainers 行動應用程式中,會由 IdentityService 實作 介面的 類別執行與 IdentityServer 的 IIdentityService 通訊。 此介面會指定實作類別必須提供 CreateAuthorizationRequestCreateLogoutRequestGetTokenAsync 方法。

登入

當使用者點選 上的 LoginViewLOGIN 按鈕時,SignInCommand會執行 類別中的 LoginViewModel ,進而執行 SignInAsync 方法。 下列程式碼範例示範此方法:

private async Task SignInAsync()  
{  
    ...  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    IsLogin = true;  
    ...  
}

這個方法會 CreateAuthorizationRequest 叫用 類別中的 IdentityService 方法,如下列程式代碼範例所示:

public string CreateAuthorizationRequest()
{
    // Create URI to authorization endpoint
    var authorizeRequest = new AuthorizeRequest(GlobalSetting.Instance.IdentityEndpoint);

    // Dictionary with values for the authorize request
    var dic = new Dictionary<string, string>();
    dic.Add("client_id", GlobalSetting.Instance.ClientId);
    dic.Add("client_secret", GlobalSetting.Instance.ClientSecret); 
    dic.Add("response_type", "code id_token");
    dic.Add("scope", "openid profile basket orders locations marketing offline_access");
    dic.Add("redirect_uri", GlobalSetting.Instance.Callback);
    dic.Add("nonce", Guid.NewGuid().ToString("N"));
    dic.Add("code_challenge", CreateCodeChallenge());
    dic.Add("code_challenge_method", "S256");

    // Add CSRF token to protect against cross-site request forgery attacks.
    var currentCSRFToken = Guid.NewGuid().ToString("N");
    dic.Add("state", currentCSRFToken);

    var authorizeUri = authorizeRequest.Create(dic); 
    return authorizeUri;
}

此方法會使用必要的參數,為 IdentityServer 的 授權端點建立 URI。 授權端點位於公開為使用者設定之基底端點連接埠 5105 的 /connect/authorize。 如需使用者設定的詳細資訊,請參閱組態管理

注意

eShopOnContainers 行動應用程式的受攻擊面會藉由將 Code Exchange 的 Proof Key (PKCE) 延伸模組實作至 OAuth 來減少。 PKCE 會保護授權碼,使其在遭到攔截時無法使用。 這是由產生祕密驗證器的用戶端所達成,在授權要求中以雜湊方式傳遞,在兌換授權碼時顯示為未隱藏。 如需 PKCE 的詳細資訊,請參閱網際網路工程任務推動小組網站上的 OAuth 公用用戶端的 Proof Key for Code Exchange (英文)。

傳回的 URI 會儲存在 LoginViewModel 類別的 LoginUrl 屬性中。 IsLogin當屬性變成 true時,WebView中的 LoginView 會變成可見。 數據 WebView 會將其 Source 屬性系結至 LoginUrl 類別的 LoginViewModel 屬性,因此當屬性設定為 IdentityServer 的授權端點時 LoginUrl ,會向 IdentityServer 提出登入要求。 當 IdentityServer 收到此要求且使用者未通過驗證時, WebView 將會重新導向至已設定的登入頁面,如圖 9-4 所示。

Login page displayed by the WebView

圖 9-4: WebView 顯示的登入頁面

登入完成後,WebView 會被重新導向至傳回 URI。 此 WebView 導覽會導致執行 LoginViewModel 類別中的 NavigateAsync 方法,如下列程式碼範例所示:

private async Task NavigateAsync(string url)  
{  
    ...  
    var authResponse = new AuthorizeResponse(url);  
    if (!string.IsNullOrWhiteSpace(authResponse.Code))  
    {  
        var userToken = await _identityService.GetTokenAsync(authResponse.Code);  
        string accessToken = userToken.AccessToken;  

        if (!string.IsNullOrWhiteSpace(accessToken))  
        {  
            Settings.AuthAccessToken = accessToken;  
            Settings.AuthIdToken = authResponse.IdentityToken;  

            await NavigationService.NavigateToAsync<MainViewModel>();  
            await NavigationService.RemoveLastFromBackStackAsync();  
        }  
    }  
    ...  
}

此方法會剖析傳回 URI 中包含的驗證回應,並提供有效的授權碼存在,它會向 IdentityServer 的 令牌端點提出要求、傳遞授權碼、PKCE 秘密驗證程式和其他必要參數。 權杖端點位於公開為使用者設定之基底端點連接埠 5105 的 /connect/token。 如需使用者設定的詳細資訊,請參閱組態管理

提示

驗證傳回 URI。 雖然 eShopOnContainers 行動應用程式不會驗證傳回 URI,但最佳做法是驗證傳回 URI 參考已知位置,以防止開啟重新導向攻擊。

如果權杖端點收到有效的授權碼和 PKCE 秘密驗證器,則會使用存取權杖、身分識別權杖和重新整理權杖來回應。 存取令牌(允許存取 API 資源)和身分識別令牌接著會儲存為應用程式設定,並執行頁面流覽。 因此,eShopOnContainers 行動裝置應用程式中的整體效果如下:前提是用戶能夠成功向 IdentityServer 進行驗證,他們會流覽至 MainView 頁面,也就是 TabbedPage 顯示為 CatalogView 其選取索引卷標的 。

如需頁面導覽的相關資訊,請參閱導覽。 如需巡覽如何 WebView 執行檢視模型方法的詳細資訊,請參閱 使用行為叫用導覽。 如需應用程式設定的相關信息,請參閱 組態管理

注意

當應用程式設定為在 中使用 SettingsView模擬服務時,eShopOnContainers 也允許模擬登入。 在此模式中,應用程式不會與 IdentityServer 通訊,而是允許使用者使用任何認證登入。

登出

當使用者點選中的 [註銷] 按鈕時,LogoutCommand會執行 類別中的 ProfileViewModel ,進而執行 LogoutAsyncProfileView方法。 這個方法會將頁面導覽至 LoginView 頁面,並將設為 trueLogoutParameter 執行個體當做參數傳遞。 如需在頁面導覽期間傳遞參數的詳細資訊,請參閱 在導覽期間傳遞參數。

建立並導覽至檢視時,會執行與檢視模型相關聯的檢視 InitializeAsync 方法,然後執行 LoginViewModel 類別的 Logout 方法,如下列程式碼範例所示:

private void Logout()  
{  
    var authIdToken = Settings.AuthIdToken;  
    var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);  

    if (!string.IsNullOrEmpty(logoutRequest))  
    {  
        // Logout  
        LoginUrl = logoutRequest;  
    }  
    ...  
}

這個方法會叫用 IdentityService 類別中的 CreateLogoutRequest 方法,將擷取自應用程式設定的身分識別權杖當做參數傳遞。 如需應用程式設定的詳細資訊,請參閱 組態管理。 下列程式碼範例示範 CreateLogoutRequest 方法:

public string CreateLogoutRequest(string token)  
{  
    ...  
    return string.Format("{0}?id_token_hint={1}&post_logout_redirect_uri={2}",   
        GlobalSetting.Instance.LogoutEndpoint,  
        token,  
        GlobalSetting.Instance.LogoutCallback);  
}

此方法會使用必要的參數,建立 IdentityServer 結束會話端點URI。 結束工作階段端點位於公開為使用者設定之基底端點連接埠 5105 的 /connect/endsession。 如需使用者設定的詳細資訊,請參閱組態管理

傳回的 URI 會儲存在 LoginViewModel 類別的 LoginUrl 屬性中。 當 IsLogin 屬性為 true時, WebView 會顯示 中的 LoginView 。 數據 WebView 會將其 Source 屬性系結至 LoginUrl 類別的 LoginViewModel 屬性,因此當 LoginUrl 屬性設定為 IdentityServer 的結束會話端點時,會向 IdentityServer 提出註銷要求。 當 IdentityServer 收到此要求時,前提是使用者已登入,就會發生註銷。 由 ASP.NET Core 之 Cookie 驗證中介軟體所管理的 Cookie 會追蹤驗證。 因此,註銷 IdentityServer 會移除驗證 Cookie,並將註銷後重新導向 URI 傳回用戶端。

在行動裝置應用程式中, WebView 將會重新導向至註銷後重新導向 URI。 此 WebView 導覽會導致執行 LoginViewModel 類別中的 NavigateAsync 方法,如下列程式碼範例所示:

private async Task NavigateAsync(string url)  
{  
    ...  
    Settings.AuthAccessToken = string.Empty;  
    Settings.AuthIdToken = string.Empty;  
    IsLogin = false;  
    LoginUrl = _identityService.CreateAuthorizationRequest();  
    ...  
}

這個方法會清除應用程式設定中的識別令牌和存取令牌,並將 屬性設定 IsLoginfalse,這會導致 WebView 頁面上的 LoginView 變成不可見。 最後,LoginUrl 屬性會被設為 IdentityServer 授權端點的 URI,其中包含必要的參數,以備下次使用者起始登入時使用。

如需頁面導覽的相關資訊,請參閱導覽。 如需巡覽如何 WebView 執行檢視模型方法的詳細資訊,請參閱 使用行為叫用導覽。 如需應用程式設定的相關信息,請參閱 組態管理

注意

當應用程式設定為在 設定 View 中使用模擬服務時,eShopOnContainers 也允許模擬註銷。 在此模式中,應用程式不會與 IdentityServer 通訊,而是清除應用程式設定中所有已儲存的權杖。

授權

驗證之後,ASP.NET Core Web API 通常需要授權存取權,這可讓服務讓某些已驗證的使用者使用 API,但並非全部使用。

您可以藉由將 Authorize 屬性套用至控制器或動作,以限制存取 ASP.NET Core MVC 路由,以限制對已驗證使用者的控制器或動作的存取,如下列程式代碼範例所示:

[Authorize]  
public class BasketController : Controller  
{  
    ...  
}

如果未經授權的用戶嘗試存取以 Authorize 屬性標示的控制器或動作,MVC 架構會傳回 401 (未經授權) HTTP 狀態代碼。

注意

您可以在 屬性上 Authorize 指定參數,以將 API 限制為特定使用者。 如需詳細資訊,請參閱 授權

IdentityServer 可以整合到授權工作流程中,以便其提供的存取權杖可控制授權。 這個方法如圖 9-5 所示。

Authorization by access token

圖 9-5: 依存取令牌授權

eShopOnContainers 行動應用程式會與身分識別微服務通訊,並在驗證程式中要求存取令牌。 接著,存取權杖會隨著存取要求,被轉送到訂購和購物籃微服務公開的 API。 存取令牌包含客戶端和使用者的相關信息。 然後,API 會使用該資訊授權,准許存取其資料。 如需如何設定 IdentityServer 以保護 API 的資訊,請參閱 設定 API 資源

設定 IdentityServer 以執行授權

若要使用 IdentityServer 執行授權,您必須將其授權中介軟體新增至 Web 應用程式的 HTTP 要求管線。 中間件會新增至 ConfigureAuth Web 應用程式的 Startup 類別中,從 Configure 方法叫用,並在 eShopOnContainers 參考應用程式的下列程式代碼範例中示範:

protected virtual void ConfigureAuth(IApplicationBuilder app)  
{  
    var identityUrl = Configuration.GetValue<string>("IdentityUrl");  
    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions  
    {  
        Authority = identityUrl.ToString(),  
        ScopeName = "basket",  
        RequireHttpsMetadata = false  
    });  
} 

此方法可確保唯有有效的存取權杖才能存取 API。 中間件會驗證傳入令牌,以確保其是從受信任的簽發者傳送,並驗證令牌是否有效,以便與接收令牌的API搭配使用。 因此,流覽至訂購或購物籃控制器會傳回 401(未經授權)HTTP 狀態代碼,指出需要存取令牌。

注意

IdentityServer 的授權中介軟體必須先新增至 Web 應用程式的 HTTP 要求管線,才能使用 app.UseMvc()app.UseMvcWithDefaultRoute() 新增 MVC。

對 API 提出存取要求

對訂購和購物籃微服務提出要求時,必須在要求中包含從IdentityServer 取得的存取令牌,如下列程式代碼範例所示:

var authToken = Settings.AuthAccessToken;  
Order = await _ordersService.GetOrderAsync(Convert.ToInt32(order.OrderNumber), authToken);

存取令牌會儲存為應用程式設定,並從平臺特定的記憶體擷取,並包含在類別中 方法的呼叫 GetOrderAsyncOrderService

同樣地,將資料傳送至 IdentityServer 保護的 API 時,也必須包含存取權杖,如下列程式碼範例所示:

var authToken = Settings.AuthAccessToken;  
await _basketService.UpdateBasketAsync(new CustomerBasket  
{  
    BuyerId = userInfo.UserId,   
    Items = BasketItems.ToList()  
}, authToken);

存取令牌會從平臺特定的記憶體擷取,並包含在類別中 方法的BasketService呼叫UpdateBasketAsync中。

在 eShopOnContainers 行動應用程式中,類別 RequestProviderHttpClient 使用 類別對 eShopOnContainers 參考應用程式所公開的 RESTful API 提出要求。 向需要授權的訂購和購物籃 API 提出要求時,要求中必須包含有效的存取權杖。 這可藉由將存取令牌新增至 實例的 HttpClient 標頭,如下列程式代碼範例所示:

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

HttpClient 類別的 DefaultRequestHeaders 屬性會公開隨每個要求一起傳送的標頭,而存取權杖則會新增至以字串 Bearer 為前置詞的 Authorization 標頭。 當要求傳送至 RESTful API 時,會擷取並驗證標頭的值 Authorization ,以確保其是從受信任的簽發者傳送,並用來判斷使用者是否有權叫用接收它的 API。

如需 eShopOnContainers 行動應用程式如何提出 Web 要求的詳細資訊,請參閱 存取遠程數據

摘要

將驗證和授權 Xamarin.Forms 整合到與 ASP.NET MVC Web 應用程式通訊的應用程式有許多方法。 eShopOnContainers 行動應用程式會使用 IdentityServer 4 的容器化身分識別微服務來執行驗證和授權。 IdentityServer 是開放原始碼 OpenID Connect 和適用於 ASP.NET Core 的 OAuth 2.0 架構,可與 ASP.NET Core 身分識別整合,以執行持有人權杖驗證。

行動應用程式會向IdentityServer 要求安全性令牌,以驗證使用者或存取資源。 存取資源時,需要授權之 API 的要求中必須包含存取權杖。 IdentityServer 的中間件會驗證連入存取令牌,以確保這些令牌是從受信任的簽發者傳送,而且它們有效,可與接收令牌的 API 搭配使用。