AddJwtBearer OnAuthenticationFailed return 自定义错误
AddJwtBearer OnAuthenticationFailed return custom error
我正在使用 Openidict。
我正在尝试 return 带有自定义状态代码的自定义消息,但我做不到。我在 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);
}
};
});
但问题是没有内容是 returned。 Chrome 开发者工具报告
(failed)
状态和
Failed to load response data
回复。
我也试过:
context.Response.WriteAsync(result).Wait();
return Task.CompletedTask;
但结果是一样的
期望的行为:
我想 return 自定义状态代码和错误信息。
请务必注意,当 401 响应为 return编辑:
如果觉得标准行为不够方便,可以使用事件模型手动处理挑战。例如:
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
};
context.Response.ContentType = "application/json";
context.Response.StatusCode = 401;
return context.Response.WriteAsync(payload.ToString());
};
});
遇到同样的问题,尝试了 Pinpoint 提供的解决方案,但它在 ASP.NET core 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;
}
};
});
请检查 .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;
},
在发现与更新包后似乎出现的异常相关的问题后,这对我有用。
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;
}
我正在使用 Openidict。
我正在尝试 return 带有自定义状态代码的自定义消息,但我做不到。我在 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);
}
};
});
但问题是没有内容是 returned。 Chrome 开发者工具报告
(failed)
状态和
Failed to load response data
回复。
我也试过:
context.Response.WriteAsync(result).Wait();
return Task.CompletedTask;
但结果是一样的
期望的行为:
我想 return 自定义状态代码和错误信息。
请务必注意,当 401 响应为 return编辑:
如果觉得标准行为不够方便,可以使用事件模型手动处理挑战。例如:
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
};
context.Response.ContentType = "application/json";
context.Response.StatusCode = 401;
return context.Response.WriteAsync(payload.ToString());
};
});
遇到同样的问题,尝试了 Pinpoint 提供的解决方案,但它在 ASP.NET core 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;
}
};
});
请检查 .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;
},
在发现与更新包后似乎出现的异常相关的问题后,这对我有用。
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;
}