环境:.NET 4.6.1,ASP.NET MVC 2,Microsoft.Owin
申请情况
代码库
启动
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管道中吃掉异常(在OAuthConfig&#39;构造函数中)
this.app.Use(async (ctx, next) =>
{
try
{
await next();
}
catch (OperationCanceledException)
{
// Eat this exception
}
});
虽然我们现在还没有启用授权,但想知道这是否可能会提出一些其他可能导致问题的设计问题。
如果需要,可以包含任何其他特定工件。 感谢
答案 0 :(得分:2)
首先,让我简单介绍一下OWIN的工作原理。值得您阅读更多相关内容,但这是一个很好的起点。
将OWIN视为请求与应用程序之间的管道,在本例中是一个MVC Web Api。管道的每个部分称为“中间件”,请求流经此管道,直到它到达您的应用程序。当请求到达管道时,流程反转,数据流回管道。因此,当数据进入应用程序并离开应用程序时,此管道的每个部分(“中间件”)都会看到数据两次。中间件可以在请求进入时查看或修改请求,或在请求离开应用程序时查看或修改响应,或者两者兼而有之。
每个中间件组件都会收到一个字典,其中包含有关请求和响应的各种数据以及一个调用下一个管道的委托。
现在为您的代码:
您的应用程序是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
变量存在问题。
希望有所帮助。