簡體   English   中英

.Net控制台應用程序調用Web API,調用另一個Web API

[英].Net Console app calling a Web API, calling another Web API

我很難理解如何重用用戶的安全令牌,以便在數據請求流經多個Web API時對其進行身份驗證。

  • Console App - C#/ Net Framework 4.7.x控制台應用程序。
  • WebAPI 1 - C#/ .Net Core 2.2 MVC WebAPI應用程序。
  • WebAPI 2 - C#/ .Net Core 2.2 MVC WebAPI應用程序。

目前,這些都是在我自己的開發盒上運行的Visual Studio 2019解決方案中配置為獨立應用程序,但是(一旦工作!!)將分別作為獨立的實體托管在Azure中。

實質上,用戶在控制台應用程序中進行身份驗證,從Azure Active Directory驗證其憑據。 在GitHub上的這個示例之后,我已經使用我的控制台應用程序成功調用WebAPI 1並返回數據。

但是,我希望WebAPI 1在調用期間調用WebAPI 2並檢索其他數據作為Console App數據集的一部分,這是我堅持的部分。

WebAPI 2在Azure門戶中配置與WebAPI 1完全相同,但不同的應用程序客戶端ID等除外。

作為示例的一部分(如上所述),我可以在將數據返回到調用Console App之前將WebAPI 1調用到Microsoft的Graph API,因此我認為我沒有辦法解決這個問題。 以下是調用Graph API的代碼:

    public async Task<string> CallGraphApiOnBehalfOfUser()
    {
        string[] scopes = { "user.read" };

        // we use MSAL.NET to get a token to call the API On Behalf Of the current user
        try
        {
            string accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUser(HttpContext, scopes);
            dynamic me = await CallGraphApiOnBehalfOfUser(accessToken);
            return me.userPrincipalName;
        }
        catch (MsalUiRequiredException ex)
        {
            _tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeader(HttpContext, scopes, ex);
            return string.Empty;
        }
    } 

    private static async Task<dynamic> CallGraphApiOnBehalfOfUserOriginal(string accessToken)
    {
        //
        // Call the Graph API and retrieve the user's profile.
        //
        HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        HttpResponseMessage response = await client.GetAsync("https://graph.microsoft.com/v1.0/me");
        string content = await response.Content.ReadAsStringAsync();
        if (response.StatusCode == HttpStatusCode.OK)
        {
            dynamic me = JsonConvert.DeserializeObject(content);
            return me;
        }

        throw new Exception(content);
    }

我的計划是將上面代碼中的URL更改為指向WebAPI 2的地址,但在身份驗證期間失敗。 如果我WebAPI 2 刪除了我的控制器上的[Authorize]類屬性,它確實成功建立連接並返回預期的數據,但是如果屬性打開,它甚至沒有在Controller上找到斷點,向我建議問題在於我正在嘗試使用的承載令牌, 或者沒有正確配置WebAPI 2。

獲取安全令牌的副本並嘗試重新使用此中途飛行也不起作用,因為我假設該令牌用於WebAPI 1 ,因此WebAPI 2WebAPI 2一起使用。

我應該像這樣做傳遞身份驗證嗎? (將用戶憑據硬編碼到能夠訪問WebAPI 2 WebAPI 1感覺很臟,所以我不想這樣做。另外,如果用戶憑據需要更改,我就會進行重新部署。 )

有沒有更好的方法來做我想做的事情?

如果你需要我提供更多信息來解釋我所做的一切,我當然可以做到。

更新1:這是Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddProtectWebApiWithMicrosoftIdentityPlatformV2(Configuration)
                .AddProtectedApiCallsWebApis(Configuration, new string[] { "user.read", "offline_access" })
                .AddInMemoryTokenCaches();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...

        app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseMvc();
    }

更新2:類似Stack Overflow帖子我發現了這個SO帖子 ,@ philippe-signoret在他的回答中描述,正是我所追求的。

更新3:調用WebAPI 2時未經授權的響應

這是我從通話中收到的錯誤消息:

{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
   Server: Kestrel
   WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
   X-SourceFiles: =?UTF-8?B?*<random-looking-code>*
   X-Powered-By: ASP.NET
   Date: Fri, 31 May 2019 09:48:31 GMT
   Content-Length: 0
}}

正如我之前提到的,如果我從Controller的類中刪除[Authorize]屬性,則調用將按預期進行。

您應該參考的示例是https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-openidconnect-aspnetcore 此示例包含在Azure AD保護的ASP.NET Core 2.0上運行的Web API。 ASP.NET Core 2.0 Web應用程序代表登錄用戶訪問Web API。

示例中的中間應用程序是Web應用程序,而不是web api,但基本原理是相同的。

我建議您先嚴格遵循此示例,以便了解如何代表用戶從web api 1調用web api 2。 請注意“ 注冊TodoListWebApp Web應用程序 ”部分下的步驟6,7:

6, From the Settings blade, select Required permissions. Select + Add, and then select Select an API. 
Type TodoListService in the textbox and press Enter. Select the web API from the list and then select the Select button. Select Select Permissions. 
Tick the checkbox next to Access TodoListService and then select the Select button. Select the Done button.

7, In the Settings blade, under API Access, select Required permissions. 
Click on the Grant Permissions and when prompted press Yes. 
Once the web app is granted access to the webapi you should see the following message: Successfully granted permissions to the application for your account. 
To grant permissions for all users, please have an admin consent to the application.

在Web應用程序中調用web api的核心代碼片段如下:

            // Because we signed-in already in the WebApp, the userObjectId is know
            string userObjectID = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;

            // Using ADAL.Net, get a bearer token to access the TodoListService
            AuthenticationContext authContext = new AuthenticationContext(AzureAdOptions.Settings.Authority, new NaiveSessionCache(userObjectID, HttpContext.Session));
            ClientCredential credential = new ClientCredential(AzureAdOptions.Settings.ClientId, AzureAdOptions.Settings.ClientSecret);
            result = await authContext.AcquireTokenSilentAsync(AzureAdOptions.Settings.TodoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

            // Retrieve the user's To Do List.
            HttpClient client = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, AzureAdOptions.Settings.TodoListBaseAddress + "/api/todolist");
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            HttpResponseMessage response = await client.SendAsync(request);

暫無
暫無

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

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