MVC Web API 中的 Owin 给出 CancelationToken 异常
Owin in MVC Web API giving CancelationToken exception
环境:.NET 4.6.1,ASP.NET MVC 2,Microsoft.Owin
申请情况
- Owin 配置为基于 OAuth 的身份验证(自己的数据库)。
- 授权属性尚未 添加。下一步
代码库
启动
public void Configuration(IAppBuilder app)
{
OAuthConfig oAuthConfig = new OAuthConfig(app, AppConfiguration);
oAuthConfig.ConfigureOAuthTokenGeneration();
oAuthConfig.ConfigureOAuthTokenConsumption();
WebApiConfig.Register(AppConfiguration);
app.UseWebApi(AppConfiguration);
// No further configuration is now allowed.
AppConfiguration.EnsureInitialized();
}
OAuthConfig
public OAuthConfig(IAppBuilder app, HttpConfiguration HttpConfiguration)
{
this.app = app;
if (OAuthConfig.HttpConfiguration == null)
OAuthConfig.HttpConfiguration = HttpConfiguration;
this.app.Use(async (ctx, next) =>
{
try
{
await next();
}
catch (OperationCanceledException)
{
// Eat this exception
}
});
}
public void ConfigureOAuthTokenGeneration()
{
var userStore = HttpConfiguration.DependencyResolver.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;
UserService.UserStore = userStore;
this.app.CreatePerOwinContext<UserService>(UserService.Create);
this.app.CreatePerOwinContext<SignInService>(SignInService.Create);
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"];
var tokenEndpoint = ConfigurationManager.AppSettings["as:OwinTokenEndpoint"]; // "/oauth/token"
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
////For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new Microsoft.Owin.PathString(tokenEndpoint),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(issuer)
};
// OAuth 2.0 Bearer Access Token Generation
this.app.UseOAuthAuthorizationServer(oAuthServerOptions);
}
public void ConfigureOAuthTokenConsumption() {
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"]; // Should have the Url of the auth server http://localhost:53025/";
byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]);
this.app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audienceId },
IssuerSecurityKeyProviders = new IIssuerSecurityKeyProvider[]
{
new SymmetricKeyIssuerSecurityKeyProvider(issuer, audienceSecret)
}
});
}
CancelledTaskHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
// Try to suppress response content when the cancellation token has fired;
// ASP.NET will log to the Application event log if there's content in this case.
if (cancellationToken.IsCancellationRequested)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return response;
}
WebApiConfig
public static void Register(HttpConfiguration config)
{
// routes and other config
// Handle CancellationToken which sometimes causes the app to hang due to orphaned responses
config.MessageHandlers.Add(new CancelledTaskMessageHandler());
}
面临的问题
在开发机器(本地测试)中,没有问题 运行 api 并消耗
部署时,windows 应用程序日志报告错误如下:
Exception type: OperationCanceledException
Exception message: The operation was canceled.
at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__27.MoveNext()
问题
- 不确定为什么 Owin 在没有请求身份验证时甚至会启动,
仅设置了处理程序。
- 因此对性能有影响吗?
已尝试
Owin 管道中的 Eating out 异常(在 OAuthConfig 的构造函数中)
this.app.Use(async (ctx, next) =>
{
try
{
await next();
}
catch (OperationCanceledException)
{
// Eat this exception
}
});
虽然我们现在没有启用授权,但想知道这是否可以暗示一些其他设计问题,这些问题可能会导致以后出现问题。
如果需要,可以包括任何其他特定工件。
谢谢
首先让我简要介绍一下 OWIN 的工作原理。值得您阅读更多相关内容,但这是一个很好的起点。
将 OWIN 视为请求与您的应用程序之间的管道,在本例中为 MVC Web Api。管道的每一部分都称为 "middleware",请求流经此管道,直到到达您的应用程序。当请求到达管道时,流程反转,数据通过管道回流。因此,此管道的每一部分("middleware")都会看到数据两次,分别是数据进入应用程序和数据离开应用程序时。中间件可以在请求进入时查看或修改请求,或者在它离开您的应用程序时查看或修改响应,或者两者兼而有之。
每个中间件组件都会收到一个字典,其中包含有关请求和响应的各种数据,以及一个调用下一段管道的委托。
现在输入您的代码:
您的应用程序是 WebApi,由这些行定义:
app.UseWebApi(AppConfiguration);
您有两个使用这些行初始化的中间件:
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"];
var tokenEndpoint = ConfigurationManager.AppSettings["as:OwinTokenEndpoint"]; // "/oauth/token"
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
////For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new Microsoft.Owin.PathString(tokenEndpoint),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(issuer)
};
// OAuth 2.0 Bearer Access Token Generation
this.app.UseOAuthAuthorizationServer(oAuthServerOptions);
然后是这些行:
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"]; // Should have the Url of the auth server http://localhost:53025/";
byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]);
this.app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audienceId },
IssuerSecurityKeyProviders = new IIssuerSecurityKeyProvider[]
{
new SymmetricKeyIssuerSecurityKeyProvider(issuer, audienceSecret)
}
});
此中间件将始终 运行。如果你在任何地方有任何属性都没有关系。
您说该错误不会发生在本地开发机器上,这意味着您很可能遇到了配置问题。您正在将设置传递到上面引用的行中的中间件。
基于此,我怀疑您的 issuer
或 tokenEndpoint
变量或(更有可能)audienceId
或 audienceSecret
变量有问题。
希望对您有所帮助。
环境:.NET 4.6.1,ASP.NET MVC 2,Microsoft.Owin
申请情况
- Owin 配置为基于 OAuth 的身份验证(自己的数据库)。
- 授权属性尚未 添加。下一步
代码库
启动
public void Configuration(IAppBuilder app)
{
OAuthConfig oAuthConfig = new OAuthConfig(app, AppConfiguration);
oAuthConfig.ConfigureOAuthTokenGeneration();
oAuthConfig.ConfigureOAuthTokenConsumption();
WebApiConfig.Register(AppConfiguration);
app.UseWebApi(AppConfiguration);
// No further configuration is now allowed.
AppConfiguration.EnsureInitialized();
}
OAuthConfig
public OAuthConfig(IAppBuilder app, HttpConfiguration HttpConfiguration)
{
this.app = app;
if (OAuthConfig.HttpConfiguration == null)
OAuthConfig.HttpConfiguration = HttpConfiguration;
this.app.Use(async (ctx, next) =>
{
try
{
await next();
}
catch (OperationCanceledException)
{
// Eat this exception
}
});
}
public void ConfigureOAuthTokenGeneration()
{
var userStore = HttpConfiguration.DependencyResolver.GetService(typeof(IUserStore<ExtendedUser, string>)) as IUserStore<ExtendedUser, string>;
UserService.UserStore = userStore;
this.app.CreatePerOwinContext<UserService>(UserService.Create);
this.app.CreatePerOwinContext<SignInService>(SignInService.Create);
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"];
var tokenEndpoint = ConfigurationManager.AppSettings["as:OwinTokenEndpoint"]; // "/oauth/token"
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
////For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new Microsoft.Owin.PathString(tokenEndpoint),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(issuer)
};
// OAuth 2.0 Bearer Access Token Generation
this.app.UseOAuthAuthorizationServer(oAuthServerOptions);
}
public void ConfigureOAuthTokenConsumption() {
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"]; // Should have the Url of the auth server http://localhost:53025/";
byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]);
this.app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audienceId },
IssuerSecurityKeyProviders = new IIssuerSecurityKeyProvider[]
{
new SymmetricKeyIssuerSecurityKeyProvider(issuer, audienceSecret)
}
});
}
CancelledTaskHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
// Try to suppress response content when the cancellation token has fired;
// ASP.NET will log to the Application event log if there's content in this case.
if (cancellationToken.IsCancellationRequested)
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
return response;
}
WebApiConfig
public static void Register(HttpConfiguration config)
{
// routes and other config
// Handle CancellationToken which sometimes causes the app to hang due to orphaned responses
config.MessageHandlers.Add(new CancelledTaskMessageHandler());
}
面临的问题
在开发机器(本地测试)中,没有问题 运行 api 并消耗
部署时,windows 应用程序日志报告错误如下:
Exception type: OperationCanceledException Exception message: The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException() at System.Web.Http.Owin.HttpMessageHandlerAdapter.<BufferResponseContentAsync>d__27.MoveNext()
问题
- 不确定为什么 Owin 在没有请求身份验证时甚至会启动, 仅设置了处理程序。
- 因此对性能有影响吗?
已尝试
Owin 管道中的 Eating out 异常(在 OAuthConfig 的构造函数中)
this.app.Use(async (ctx, next) =>
{
try
{
await next();
}
catch (OperationCanceledException)
{
// Eat this exception
}
});
虽然我们现在没有启用授权,但想知道这是否可以暗示一些其他设计问题,这些问题可能会导致以后出现问题。
如果需要,可以包括任何其他特定工件。 谢谢
首先让我简要介绍一下 OWIN 的工作原理。值得您阅读更多相关内容,但这是一个很好的起点。
将 OWIN 视为请求与您的应用程序之间的管道,在本例中为 MVC Web Api。管道的每一部分都称为 "middleware",请求流经此管道,直到到达您的应用程序。当请求到达管道时,流程反转,数据通过管道回流。因此,此管道的每一部分("middleware")都会看到数据两次,分别是数据进入应用程序和数据离开应用程序时。中间件可以在请求进入时查看或修改请求,或者在它离开您的应用程序时查看或修改响应,或者两者兼而有之。
每个中间件组件都会收到一个字典,其中包含有关请求和响应的各种数据,以及一个调用下一段管道的委托。
现在输入您的代码:
您的应用程序是 WebApi,由这些行定义:
app.UseWebApi(AppConfiguration);
您有两个使用这些行初始化的中间件:
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"];
var tokenEndpoint = ConfigurationManager.AppSettings["as:OwinTokenEndpoint"]; // "/oauth/token"
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
////For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new Microsoft.Owin.PathString(tokenEndpoint),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat(issuer)
};
// OAuth 2.0 Bearer Access Token Generation
this.app.UseOAuthAuthorizationServer(oAuthServerOptions);
然后是这些行:
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
var issuer = ConfigurationManager.AppSettings["as:IssuerServer"]; // Should have the Url of the auth server http://localhost:53025/";
byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]);
this.app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audienceId },
IssuerSecurityKeyProviders = new IIssuerSecurityKeyProvider[]
{
new SymmetricKeyIssuerSecurityKeyProvider(issuer, audienceSecret)
}
});
此中间件将始终 运行。如果你在任何地方有任何属性都没有关系。
您说该错误不会发生在本地开发机器上,这意味着您很可能遇到了配置问题。您正在将设置传递到上面引用的行中的中间件。
基于此,我怀疑您的 issuer
或 tokenEndpoint
变量或(更有可能)audienceId
或 audienceSecret
变量有问题。
希望对您有所帮助。