Как заполняются OwinContext.Request.Path и PathBase?
Я пишу свое собственное промежуточное ПО OWIN для потока кода авторизации OpenID Connect на основе других примеров в проекте Katana.
В рамках этого я должен создать пару URI, например URI перенаправления и URL-адрес возврата.
Другие примеры в Katana делают это путем конкатенации частей из текущего запроса, например, в CookieAuthenticationHandler
loginUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase +
Options.LoginPath +
new QueryString(Options.ReturnUrlParameter, currentUri);
Мой вопрос в том, какие правила определяют то, что заканчивается в двух свойствах пути:
OwinContext.Request.Path
OwinContext.Request.PathBase
Я попытался проверить эти свойства, поскольку запрос проходит через разные обработчики в нижеприведенном конвейере для запроса:
"https://localhost/Client/login" // Where Client is a virtual directory in IIS
Результат:
- В сопоставленном обработчике для /login, PathBase = "/Client/Login".
- Но, когда запрос переходит к методу ApplyResponseChallengeAsync в моем QuillCodeFlowHandler на пути назад для одного и того же запроса, PathBase = "/Client" и Path = "/Login".
Таким образом, не зная "правил" для того, как эти значения заполняются, а затем изменились, трудно построить URI, используя их. Если кто-нибудь может объяснить, будет очень признателен.
Вывод моей конфигурации:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
LoginPath = new PathString("/Login")
});
app.UseQuillCodeFlowAuthentication(new QuillCodeFlowOptions());
app.Map("/login", map =>
{
map.Run(async ctx =>
{
if (ctx.Authentication.User == null ||
!ctx.Authentication.User.Identity.IsAuthenticated)
{
var authenticationProperties = new AuthenticationProperties();
[...]
ctx.Authentication.Challenge(authenticationProperties,
QuillCodeFlowDefaults.AuthenticationType);
спецификация OWIN дает некоторое объяснение, и метод Microsoft.Owin.Host.HttpListener.GetPathAndQuery, кажется, где исходные переменные пути заданы первоначально.
Ответы
Ответ 1
При использовании конструкции
app.Map("/login", map => [...]
В этом случае используется
Owin.MapExtensions.Map
который строит экземпляр
Microsoft.Owin.Mapping.MapMiddleware
для кода, который требует выполнения.
Поведение, которое я видел, объясняется в методе Invoke этого промежуточного программного обеспечения:
public async Task Invoke(IDictionary<string, object> environment)
{
IOwinContext context = new OwinContext(environment);
PathString path = context.Request.Path;
PathString remainingPath;
if (path.StartsWithSegments(_options.PathMatch, out remainingPath))
{
// Update the path
PathString pathBase = context.Request.PathBase;
context.Request.PathBase = pathBase + _options.PathMatch;
context.Request.Path = remainingPath;
await _options.Branch(environment);
context.Request.PathBase = pathBase;
context.Request.Path = path;
}
else
{
await _next(environment);
}
}
В основном код изменяет Path и PathBase перед запуском делегата (ожидание _options.Branch(среда)), а затем возвращает их к исходным значениям после завершения выполнения.
Следовательно, объясняется поведение, которое я видел.