使用 Microsoft.Identity.Web 時,呼叫 API 有三種使用方式選項:
選項 1:使用 SDK 呼叫 Microsoft Graph
在此案例中,您可以透過新增 Microsoft.Identity.Web.GraphServiceClient NuGet 套件,並依照程式碼設定中的指定,在 Startup.cs 中包含 .AddMicrosoftGraph()
來呼叫 Microsoft Graph。 然後,您可以直接將 GraphServiceClient
插入控制器或頁面建構函式,以在動作中使用。 下列範例 Razor 頁面顯示已登入使用者的相片。
[Authorize]
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public class IndexModel : PageModel
{
private readonly GraphServiceClient _graphServiceClient;
public IndexModel(GraphServiceClient graphServiceClient)
{
_graphServiceClient = graphServiceClient;
}
public async Task OnGet()
{
var user = await _graphServiceClient.Me.GetAsync();
try
{
using (var photoStream = await _graphServiceClient.Me.Photo.Content.GetAsync())
{
byte[] photoByte = ((MemoryStream)photoStream).ToArray();
ViewData["photo"] = Convert.ToBase64String(photoByte);
}
ViewData["name"] = user.DisplayName;
}
catch (Exception)
{
ViewData["photo"] = null;
}
}
}
如需完整範例,請參閱呼叫 Microsoft Graph 的 ASP.NET Core Web 應用程式。
選項 2:使用協助程式類別呼叫下游 Web API
您想要呼叫 Web API 而不是 Microsoft Graph。 在此情況下,您已依照程式碼設定中的指定在 Startup.cs 中新增 AddDownstreamApi
,您可以直接在控制器或頁面建構函式中插入 IDownstreamApi
服務,並於動作中使用:
[Authorize]
[AuthorizeForScopes(ScopeKeySection = "TodoList:Scopes")]
public class TodoListController : Controller
{
private IDownstreamApi _downstreamApi;
private const string ServiceName = "TodoList";
public TodoListController(IDownstreamApi downstreamApi)
{
_downstreamApi = downstreamApi;
}
public async Task<ActionResult> Details(int id)
{
var value = await _downstreamApi.CallApiForUserAsync(
ServiceName,
options =>
{
options.RelativePath = $"me";
});
return View(value);
}
}
CallWebApiForUserAsync
也有強型別泛型覆寫,可讓您直接接收物件。 例如,下列方法接收 Todo
執行個體,此為 Web API 所傳回 JSON 的強型別表示法。
// GET: TodoList/Details/5
public async Task<ActionResult> Details(int id)
{
var value = await _downstreamApi.CallApiForUserAsync<object, Todo>(
ServiceName,
null,
options =>
{
options.HttpMethod = HttpMethod.Get;
options.RelativePath = $"api/todolist/{id}";
});
return View(value);
}
如需完整範例,請參閱呼叫 API 的 ASP.NET Core Web 應用程式
選項 3:在不使用協助程式類別的情況下呼叫下游 Web API
您已決定使用 IAuthorizationHeaderProvider
服務手動取得權杖,而現在需要使用此權杖。 在此情況下,下列程式碼延續呼叫 Web API 的 Web 應用程式:取得應用程式的權杖中顯示的範例程式碼。 Web 應用程式控制器的動作中呼叫這段程式碼。
取得權杖之後,就當作為持有人權杖來呼叫下游 API,在此案例中為 Microsoft Graph。
public async Task<IActionResult> Profile()
{
// Acquire the access token.
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await IAuthorizationHeaderProvider.GetAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient httpClient = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
var response = await httpClient.GetAsync($"{webOptions.GraphApiUrl}/beta/me");
if (response.StatusCode == HttpStatusCode.OK)
{
var content = await response.Content.ReadAsStringAsync();
dynamic me = JsonConvert.DeserializeObject(content);
ViewData["Me"] = me;
}
return View();
}
注意
您可以使用相同的準則來呼叫任何 Web API。
大部分 Azure Web API 都提供 SDK 來簡化呼叫 API,Microsoft Graph 就是如此。
使用 Microsoft.Identity.Web 時,呼叫 API 有三種使用方式選項:
選項 1:使用 OWIN 應用程式中的 SDK 呼叫 Microsoft Graph
您想要呼叫 Microsoft Graph。 在此案例中,您已依照程式碼設定中的指定在 Startup.cs 中新增 AddMicrosoftGraph
,您可以使用控制器上的 GetGraphServiceClient()
擴充方法在控制器或頁面建構函式中取得 GraphServiceClient
以在動作中使用。 下列範例顯示已登入使用者的相片。
[Authorize]
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public class HomeController : Controller
{
public async Task GetIndex()
{
var graphServiceClient = this.GetGraphServiceClient();
var user = await graphServiceClient.Me.GetAsync();
try
{
using (var photoStream = await graphServiceClient.Me.Photo.Content.GetAsync())
{
byte[] photoByte = ((MemoryStream)photoStream).ToArray();
ViewData["photo"] = Convert.ToBase64String(photoByte);
}
ViewData["name"] = user.DisplayName;
}
catch (Exception)
{
ViewData["photo"] = null;
}
}
}
如需完整範例,請參閱呼叫 Microsoft Graph 的 ASP.NET OWIN Web 應用程式
選項 2:使用 OWIN 應用程式中的協助程式類別呼叫下游 Web API
您想要呼叫 Web API 而不是 Microsoft Graph。 在此情況下,您已依照程式碼設定中的指定在 Startup.cs 中新增 AddDownstreamApi
,您可以透過呼叫控制器上的 GetDownstreamApi
擴充方法在控制器中取得 IDownstreamApi
服務。
[Authorize]
public class TodoListController : Controller
{
public async Task<ActionResult> Details(int id)
{
var downstreamApi = this.GetDownstreamApi();
var value = await downstreamApi.CallApiForUserAsync(
ServiceName,
options =>
{
options.RelativePath = $"me";
});
return View(value);
}
}
CallApiForUserAsync
也有強型別泛型覆寫,可讓您直接接收物件。 例如,下列方法接收 Todo
執行個體,此為 Web API 所傳回 JSON 的強型別表示法。
// GET: TodoList/Details/5
public async Task<ActionResult> Details(int id)
{
var downstreamApi = this.GetDownstreamApi();
var value = await downstreamApi.CallApiForUserAsync<object, Todo>(
ServiceName,
null,
options =>
{
options.HttpMethod = HttpMethod.Get;
options.RelativePath = $"api/todolist/{id}";
});
return View(value);
}
選項 3:在不使用 OWIN 應用程式中的協助程式類別的情況下呼叫下游 Web API
您已決定使用 IAuthorizationHeaderProvider
服務取得授權標頭,現在必須在 HttpClient 或 HttpRequest 中使用。 在此情況下,下列程式碼延續呼叫 Web API 的 Web 應用程式:取得應用程式的權杖中顯示的範例程式碼。 Web 應用程式控制器的動作中呼叫這段程式碼。
public async Task<IActionResult> Profile()
{
// Acquire the access token.
string[] scopes = new string[]{"user.read"};
var IAuthorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string authorizationHeader = await IAuthorizationHeaderProvider.GetAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient httpClient = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
var response = await httpClient.GetAsync($"{webOptions.GraphApiUrl}/beta/me");
if (response.StatusCode == HttpStatusCode.OK)
{
var content = await response.Content.ReadAsStringAsync();
dynamic me = JsonConvert.DeserializeObject(content);
ViewData["Me"] = me;
}
return View();
}
private String getUserInfoFromGraph(String accessToken) throws Exception {
// Microsoft Graph user endpoint
URL url = new URL("https://graph.microsoft.com/v1.0/me");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set the appropriate header fields in the request header.
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
conn.setRequestProperty("Accept", "application/json");
String response = HttpClientHelper.getResponseStringFromConn(conn);
int responseCode = conn.getResponseCode();
if(responseCode != HttpURLConnection.HTTP_OK) {
throw new IOException(response);
}
JSONObject responseObject = HttpClientHelper.processResponse(responseCode, response);
return responseObject.toString();
}
成功擷取權杖之後,程式碼會使用 axios 套件來查詢 API 端點並擷取 JSON 結果。
/**
* Attaches a given access token to a MS Graph API call
* @param endpoint: REST API endpoint to call
* @param accessToken: raw access token string
*/
async function fetch(endpoint, accessToken) {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`
}
};
console.log(`request made to ${endpoint} at: ` + new Date().toString());
try {
const response = await axios.get(endpoint, options);
return await response.data;
} catch (error) {
throw new Error(error);
}
}
成功擷取權杖之後,程式碼會使用要求套件來查詢 API 端點並擷取 JSON 結果。
@app.route("/call_downstream_api")
def call_downstream_api():
token = auth.get_token_for_user(app_config.SCOPE)
if "error" in token:
return redirect(url_for("login"))
# Use access token to call downstream api
api_result = requests.get(
app_config.ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']},
timeout=30,
).json()
return render_template('display.html', result=api_result)