Хобрук: Ваш путь к мастерству в программировании

Метод «HttpRequestBase.GetBufferlessInputStream» не найден при использовании аутентификации owin на моно

Я развернул проект веб-API Asp.Net на своем сервере CentOS с монофонической версией 4.3.0 (скомпилирован из ветки моно-4.2.1.36, выпущенной 2 дня назад). Я построил проект, используя шаблон веб-API enpty VS2015, и добавил аутентификацию owin, пытаясь заставить веб-API работать с аутентификацией с использованием токенов-носителей.

Я размещаю проект на сервере Apache, используя mod_mono.

При локальном запуске проекта на моем компьютере с Windows все работает отлично. В Linux, когда я отправляю http POST в конечную точку /token, сервер возвращает 200 OK, но без какой-либо полезной нагрузки ответа (которая будет включать токен носителя, необходимый клиенту для аутентификации последующих запросов). В то же время сервер регистрирует исключение (следующее).

System.MissingMethodException: Method 'HttpRequestBase.GetBufferlessInputStream' not found.
  at Microsoft.Owin.Host.SystemWeb.CallStreams.InputStream.get_Stream () <0xb0e339b8 + 0x00013> in <filename unknown>:0
  at Microsoft.Owin.Host.SystemWeb.CallStreams.DelegatingStream.get_CanRead () <0xb0e45eb0 + 0x00013> in <filename unknown>:0
  at System.IO.StreamReader..ctor (System.IO.Stream stream, System.Text.Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean leaveOpen) <0xb0e5d790 + 0x0005f> in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) System.IO.StreamReader:.ctor (System.IO.Stream,System.Text.Encoding,bool,int,bool)
  at Microsoft.Owin.OwinRequest+<ReadFormAsync>d__0.MoveNext () <0xb0e33510 + 0x000f3> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0xb0e34a68 + 0x0002b> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0xb0e346d0 + 0x000bb> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0xb0e34588 + 0x0007f> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) <0xb270df98 + 0x00033> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () <0xb270e1d0 + 0x00017> in <filename unknown>:0
  at Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler+<InvokeTokenEndpointAsync>d__22.MoveNext () <0xb0e2f118 + 0x00463> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0xb0e34a68 + 0x0002b> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0xb0e346d0 + 0x000bb> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0xb0e34588 + 0x0007f> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) <0xb270df98 + 0x00033> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () <0xb270df70 + 0x00013> in <filename unknown>:0
  at Microsoft.Owin.Security.OAuth.OAuthAuthorizationServerHandler+<InvokeAsync>d__0.MoveNext () <0xb270e790 + 0x007a7> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0xb0e34a68 + 0x0002b> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0xb0e346d0 + 0x000bb> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0xb0e34588 + 0x0007f> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) <0xb270df98 + 0x00033> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult () <0xb270f5b0 + 0x00013> in <filename unknown>:0
  at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1+<Invoke>d__0[TOptions].MoveNext () <0xb270b2a0 + 0x0030f> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0xb0e34a68 + 0x0002b> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) <0xb0e346d0 + 0x000bb> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) <0xb0e34588 + 0x0007f> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) <0xb270df98 + 0x00033> in <filename unknown>:0
  at System.Runtime.CompilerServices.TaskAwaiter.GetResult () <0xb270df70 + 0x00013> in <filename unknown>:0
  at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage+<RunApp>d__5.MoveNext () <0xb270aa98 + 0x00173> in <filename unknown>:0

После поиска в Google я обнаружил, что это исключение было исправлено в другом пространстве имен, но обратите внимание, что оно возникает в Microsoft.Owin.Host.SystemWeb.

Есть ли обходной путь, чтобы избавиться от исключения, и есть ли у кого-нибудь информация о том, является ли это исключение причиной поведения, с которым я сталкиваюсь, или есть что-то еще, что я могу попробовать, чтобы заставить работать аутентификацию на основе токена-носителя?

В моем AuthorizationServerProvider я реализую следующие методы: (также при работе в Linux заголовки ответов не включают Access-Control-Allow-Origin, как в Windows)

public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
  context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
  context.Validated();
  return Task.FromResult<object>(null);
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    //check credentials

    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); //etc

    var props = new AuthenticationProperties(new Dictionary<string, string>
    {
       { "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId },
       { "userName", context.UserName }
    });

    var ticket = new AuthenticationTicket(identity, props);
    context.Validated(ticket);
}

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}

Мой Startup.cs выглядит так:

public void Configuration(IAppBuilder app)
{
    ConfigureOAuth(app);

    HttpConfiguration config = new HttpConfiguration(); 
    config.Filters.Add(new AuthorizeAttribute());
    WebApiConfig.Register(config); 

    GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
    GlobalConfiguration.Configuration.Filters.Add(new AuthorizeAttribute());

    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);  
    app.UseWebApi(config);
}

public void ConfigureOAuth(IAppBuilder app)
{
    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(15),
        Provider = new BoaAuthorizationServerProvider(),

        RefreshTokenProvider = new BoaRefreshTokenProvider(),
        ApplicationCanDisplayErrors = true,
    };
    // Enable the application to use bearer tokens to authenticate users
    app.UseOAuthBearerTokens(OAuthServerOptions);
}

РЕДАКТИРОВАТЬ:

Еще немного информации по этому поводу:

Я попробовал старый трюк remove-the-problematic-dll, и я больше не получаю это исключение, но, тем не менее, я получаю внутреннюю ошибку сервера 500 при отправке http POST в конечную точку токена (то же самое, что работает на окнах) .

Это исключение:

System.Web.HttpException
Method 'POST' is not allowed when accessing file '/webapitest/token'

Description: HTTP 500.Error processing request.
Details: Error processing request.
Exception stack trace:
   at System.Web.DefaultHttpHandler.BeginProcessRequest (System.Web.HttpContext context, System.AsyncCallback callback, System.Object state) in <filename unknown>:line 0
   at System.Web.HttpApplication+<Pipeline>c__Iterator1.MoveNext () in <filename unknown>:line 0
   at System.Web.HttpApplication.Tick () in <filename unknown>:line 0

Обратите внимание на конфигурацию запуска выше, есть ли там что-то, что моно не поддерживает? Если нет, то это похоже либо на проблему с конфигурацией, либо на ошибку в моно, поскольку кто-то ранее прокомментировал, что они получают то же самое MissingMethodException для GetBufferlessInputStream, что и в Ubuntu. Затем этот комментарий был удален.


Ответы:


1

Эта ошибка все еще воспроизводится в моно-сборках, загруженных из официальных репозиториев (похоже, что в этом коммите были реализованы правильные GetBufferlessInputStream и GetBufferedInputStream: ">303d876370017774445c71736cf34e851e5cb037).

Самым простым способом для меня было обновить зависимые библиотеки из репозитория nightlybuild (не нужно компилировать весь проект, а обновлять только необходимые библиотеки для экономии места на диске). Инструкции по обновлению для Debian:

echo "deb http://download.mono-project.com/repo/debian nightly main" | sudo tee /etc/apt/sources.list.d/mono-nightly.list
sudo apt-get update
sudo apt-get install libmono-system-net-http-webrequest4.0-cil

(любая другая http-библиотека libmono тоже должна работать, список необходимых пакетов будет составлен автоматически)

04.03.2016
Новые материалы

Решения DBA Metrix
DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

Начало работы с Блум
Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

Создание кнопочного меню с использованием HTML, CSS и JavaScript
Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

Внедрите OAuth в свои веб-приложения для повышения безопасности
OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

Классы в JavaScript
class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

Как свинг-трейдеры могут использовать ИИ для больших выигрышей
По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

Как построить любой стол
Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...