我在使用aspnet核心構建的組織中使用了web api。我們想發佈一個android應用程序,一個mvc5應用程序和一個aspnet核心mvc6應用程序使用的api。我如何在Azure中配置web api,以便使用它的應用程序不要求登錄。網絡應用程序已經被天藍色保護,但是當我用azure保護web api時,當我向它發出請求時,會得到一個401。我不知道如何在azure中配置應用程序,或者我必須在api中配置的代碼。我讀了很多,但我沒有找到一種方法來實現這一點。我想要的只是登錄我的網絡應用程序,並且Web應用程序開始通過ajax向Web api提問數據。我應該發送ajax請求某種裸機標記,但我不知道我必須在azure和應用程序中執行什麼配置。我希望你能幫助我。Aspnet核心web api使用Azure保護
回答
在使用Azure AD保護Web API之後,我們需要發送訪問令牌以請求Web API進行授權。當用戶從Web應用程序調用Web API時,我們可以獲取訪問令牌。這裏是收購Web應用程序的令牌,供大家參考代碼:
public async Task<IActionResult> Index()
{
AuthenticationResult result = null;
List<TodoItem> itemList = new List<TodoItem>();
try
{
string userObjectID = (User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID, HttpContext.Session));
ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.ClientSecret);
result = await authContext.AcquireTokenSilentAsync(Startup.TodoListResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
//
// Retrieve the user's To Do List.
//
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, TodoListBaseAddress + "/api/todolist");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
//
// Return the To Do List in the view.
//
if (response.IsSuccessStatusCode)
{
List<Dictionary<String, String>> responseElements = new List<Dictionary<String, String>>();
JsonSerializerSettings settings = new JsonSerializerSettings();
String responseString = await response.Content.ReadAsStringAsync();
responseElements = JsonConvert.DeserializeObject<List<Dictionary<String, String>>>(responseString, settings);
foreach (Dictionary<String, String> responseElement in responseElements)
{
TodoItem newItem = new TodoItem();
newItem.Title = responseElement["title"];
newItem.Owner = responseElement["owner"];
itemList.Add(newItem);
}
return View(itemList);
}
else
{
//
// If the call failed with access denied, then drop the current access token from the cache,
// and show the user an error indicating they might need to sign-in again.
//
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
var todoTokens = authContext.TokenCache.ReadItems().Where(a => a.Resource == Startup.TodoListResourceId);
foreach (TokenCacheItem tci in todoTokens)
authContext.TokenCache.DeleteItem(tci);
ViewBag.ErrorMessage = "UnexpectedError";
TodoItem newItem = new TodoItem();
newItem.Title = "(No items in list)";
itemList.Add(newItem);
return View(itemList);
}
}
}
catch (Exception ee)
{
if (HttpContext.Request.Query["reauth"] == "True")
{
//
// Send an OpenID Connect sign-in request to get a new set of tokens.
// If the user still has a valid session with Azure AD, they will not be prompted for their credentials.
// The OpenID Connect middleware will return to this controller after the sign-in response has been handled.
//
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme);
}
//
// The user needs to re-authorize. Show them a message to that effect.
//
TodoItem newItem = new TodoItem();
newItem.Title = "(Sign-in required to view to do list.)";
itemList.Add(newItem);
ViewBag.ErrorMessage = "AuthorizationRequired";
return View(itemList);
}
//
// If the call failed for any other reason, show the user an error.
//
return View("Error");
}
,下面將其使用JwtBearerAppBuilderExtensions到OpenIdConnect承載認證功能添加到一個HTTP應用程序管道用於Web API來驗證的代碼示例令牌:
public class Startup
{
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Add the console logger.
loggerFactory.AddConsole(LogLevel.Debug);
// Configure the app to use Jwt Bearer Authentication
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAD:Tenant"]),
Audience = Configuration["AzureAd:Audience"],
});
}
}
完整的示例代碼,您可以參考here。
注意:要成功運行此示例中,我們需要修改標題和業主爲小寫冠軍,所有者在Web應用程序的ToDoController:
foreach (Dictionary<String, String> responseElement in responseElements)
{
TodoItem newItem = new TodoItem();
newItem.Title = responseElement["title"];
newItem.Owner = responseElement["owner"];
itemList.Add(newItem);
}
我已經看過這個示例。在這種情況下,當應用程序以編程方式調用api時,用戶是不是第一次要求他的憑據?這是我想要避免的。 – snekkke
在這種情況下,用戶只需輸入他們的憑證即可在應用程序中登錄。用戶登錄後,它可以獲取Web API的令牌,而無需用戶再次輸入憑證。這是否適合你的場景? –
@snekkke我不理解:'是不是用戶要求他的憑據......'你想支持什麼樣的場景? –
您可以使用Azure OpenIdConnect用於聯合身份驗證。 https://github.com/Azure-:
Calling a web API in a web app using Azure AD and OpenID Connect
如果你正在尋找從瀏覽器撥打電話到一個網站,你可能想從這個樣品得到一些想法 - 微軟下面一篇好文章samples/active-directory-angularjs-singlepageapp –