【发布时间】:2018-07-19 08:12:02
【问题描述】:
我不知道这是否真的可行,但我认为值得一试。
可能还有其他更好的模式(如果你知道,请告诉我,我会查找它们)来做到这一点,但我只是想知道这是否可能。
当您必须调用 API 时,您可以使用 HttpClient 直接在控制器中执行此操作,如下所示:
[Authorize]
public async Task<IActionResult> Private()
{
//Example: get some access token to use in api call
var accessToken = await HttpContext.GetTokenAsync("access_token");
//Example: do an API call direcly using a static HttpClient wrapt in a service
var request = new HttpRequestMessage(HttpMethod.Get, "https://example.com/api/some/endpoint");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await _client.Client.SendAsync(request);
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
//Handle situation where user is not authenticated
var rederectUrl = "/account/login?returnUrl="+Request.Path;
return Redirect(rederectUrl);
}
if (response.StatusCode == HttpStatusCode.Forbidden)
{
//Handle situation where user is not authorized
return null;
}
var text = await response.Content.ReadAsStringAsync();
Result result = JObject.Parse(text).ToObject<Result>();
return View(result);
}
当您这样做时,您将不得不一遍又一遍地重用一些代码。您可以只创建一个存储库,但对于某些情况,这将是多余的,您只想进行一些快速而肮脏的 API 调用。
现在我想知道的是,当我们将设置 Authorization 标头或处理 401 和 403 响应的逻辑移到控制器之外时,您如何重定向或控制控制器的操作。
假设我为 HttpClient 创建了一个中间件,如下所示:
public class ResourceGatewayMessageHandler : HttpClientHandler
{
private readonly IHttpContextAccessor _contextAccessor;
public ResourceGatewayMessageHandler(IHttpContextAccessor context)
{
_contextAccessor = context;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//Retrieve acces token from token store
var accessToken = await _contextAccessor.HttpContext.GetTokenAsync("access_token");
//Add token to request
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
//Execute request
var response = await base.SendAsync(request, cancellationToken);
//When 401 user is probably not logged in any more -> redirect to login screen
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
//Handle situation where user is not authenticated
var context = _contextAccessor.HttpContext;
var rederectUrl = "/account/login?returnUrl="+context.Request.Path;
context.Response.Redirect(rederectUrl); //not working
}
//When 403 user probably does not have authorization to use endpoint
if (response.StatusCode == HttpStatusCode.Forbidden)
{
//Handle situation where user is not authorized
}
return response;
}
}
我们可以这样请求:
[Authorize]
public async Task<IActionResult> Private()
{
//Example: do an API call direcly using a static HttpClient initiated with Middleware wrapt in a service
var response = await _client.Client.GetAsync("https://example.com/api/some/endpoint");
var text = await response.Content.ReadAsStringAsync();
Result result = JObject.Parse(text).ToObject<Result>();
return View(result);
}
这里的问题是context.Response.Redirect(rederectUrl); 不起作用。它不会中断重定向流。是否有可能实现这一点,你将如何解决这个问题?
【问题讨论】:
标签: c# asp.net asp.net-core-mvc middleware