使用 Microsoft.Identity.Web 时,有三个用于调用 API 的使用选项:
选项 1:使用 SDK 调用 Microsoft Graph
在此方案中,通过添加 Microsoft.Identity.Web.GraphServiceClient NuGet 包并在 Startup.cs 中加入 .AddMicrosoftGraph()
(如代码配置中所指定)来调用 Microsoft Graph。 然后,可以直接将 GraphServiceClient
注入你的控制器或页面构造函数,以在操作中使用它。 以下示例 Razor 页面显示已登录用户的照片。
[Authorize]
[AuthorizeForScopes(Scopes = new[] { "https://microsoftgraph.chinacloudapi.cn/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
你想要调用 Microsoft Graph 以外的 Web API。 在这种情况下,你按代码配置中指定的那样将 AddDownstreamApi
添加到 Startup.cs 中,然后可以直接将 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[]{"https://microsoftgraph.chinacloudapi.cn/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 都提供了可简化 API 调用的 SDK,Microsoft Graph 就是这样。
使用 Microsoft.Identity.Web 时,有三个用于调用 API 的使用选项:
选项 1:使用 SDK 从 OWIN 应用调用 Microsoft Graph
你要调用 Microsoft Graph。 在此方案中,你已按代码配置中的指定将AddMicrosoftGraph
添加到Startup.cs 中,现可通过使用控制器上的GetGraphServiceClient()
扩展方法在控制器或页构造函数中获取GraphServiceClient
,以便在操作中使用。 以下示例显示已登录用户的照片。
[Authorize]
[AuthorizeForScopes(Scopes = new[] { "https://microsoftgraph.chinacloudapi.cn/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
你想要调用 Microsoft Graph 以外的 Web API。 在此方案中,你已按代码配置中的指定将AddDownstreamApi
添加到Startup.cs中,现可通过调用控制器上的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[]{"https://microsoftgraph.chinacloudapi.cn/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://microsoftgraph.chinacloudapi.cn/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)