Я развернул проект веб-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. Затем этот комментарий был удален.