我正在使用Openidict
我试图返回自定义状态代码的自定义消息,但我无法做到。我在startup.cs
中的配置:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.Authority = this.Configuration["Authentication:OpenIddict:Authority"];
o.Audience = "MyApp"; //Also in Auhorization.cs controller.
o.RequireHttpsMetadata = !this.Environment.IsDevelopment();
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = HttpStatusCodes.AuthenticationFailed;
context.Response.ContentType = "application/json";
var err = this.Environment.IsDevelopment() ? context.Exception.ToString() : "An error occurred processing your authentication.";
var result = JsonConvert.SerializeObject(new {err});
return context.Response.WriteAsync(result);
}
};
});
但问题是没有返回内容。 Chrome开发者工具报告
(失败)
状态和
无法加载响应数据
回应。
我也尝试过:
context.Response.WriteAsync(result).Wait();
return Task.CompletedTask;
但结果是一样的。
所需行为
我想返回自定义状态代码,并显示错误信息。
答案 0 :(得分:9)
面临同样的问题,尝试了Pinpoint提供的解决方案,但它在ASP.NET核心2.0上对我没有用。但基于Pinpoint的解决方案和一些反复试验,以下代码适用于我。
var builder = services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.Authority = "http://192.168.0.110/auth/realms/demo";
o.Audience = "demo-app";
o.RequireHttpsMetadata = false;
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
c.Response.WriteAsync(c.Exception.ToString()).Wait();
return Task.CompletedTask;
},
OnChallenge = c =>
{
c.HandleResponse();
return Task.CompletedTask;
}
};
});
答案 1 :(得分:6)
值得注意的是,当返回401响应时,aspnet-contrib OAuth2验证和MSFT JWT处理程序都会自动返回包含错误代码/描述的WWW-Authenticate
响应头:
如果您认为标准行为不够方便,可以使用事件模型手动处理挑战。 E.g:
services.AddAuthentication()
.AddJwtBearer(options =>
{
options.Authority = "http://localhost:54540/";
options.Audience = "resource_server";
options.RequireHttpsMetadata = false;
options.Events = new JwtBearerEvents();
options.Events.OnChallenge = context =>
{
// Skip the default logic.
context.HandleResponse();
var payload = new JObject
{
["error"] = context.Error,
["error_description"] = context.ErrorDescription,
["error_uri"] = context.ErrorUri
};
return context.Response.WriteAsync(payload.ToString());
};
});
答案 2 :(得分:0)
请检查.net core 2.1的以下代码
OnAuthenticationFailed =context =>
{
context.Response.OnStarting(async () =>
{
context.NoResult();
context.Response.Headers.Add("Token-Expired", "true");
context.Response.ContentType = "text/plain";
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await context.Response.WriteAsync("Un-Authorized");
});
return Task.CompletedTask;
},
答案 3 :(得分:0)
这是在发现与更新包之后似乎出现的与该异常相关的问题之后对我有用的东西。
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
实现如下,
OnAuthenticationFailed = context =>
{
context.NoResult();
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json";
string response =
JsonConvert.SerializeObject("The access token provided is not valid.");
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
response =
JsonConvert.SerializeObject("The access token provided has expired.");
}
context.Response.WriteAsync(response);
return Task.CompletedTask;
},
OnChallenge = context =>
{
context.HandleResponse();
return Task.CompletedTask;
}