我有一个问题,如果我手动转到登录后的页面,我会在我的一个保单句柄中遇到异常,因为它找不到 claim 。
为什么会发生这种情况而不是将用户重定向到登录页面,因为他没有通过身份验证?我什至设置了身份验证方案,因为我所有的页面都有
[Authorize("scheme"), Policy = "policy"]
这是我的整个启动代码
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddCookie("ProductionAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Production/Index");
options.LogoutPath = new PathString("/Production/Logout");
options.AccessDeniedPath = new PathString("/Production/AccessDenied/");
options.SlidingExpiration = true;
})
.AddCookie("AdministrationAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Administration/Index");
options.LogoutPath = new PathString("/Administration/Logout");
options.AccessDeniedPath = new PathString("/Administration/AccessDenied/");
options.SlidingExpiration = true;
});
services.AddAuthorization(options =>
{
options.AddPolicy("HasArranqueActivo", policy =>
policy.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ProductionAuth")
.Requirements.Add(new HasArranqueActivoRequirement()
));
options.AddPolicy("HasArranqueInactivo", policy =>
policy.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ProductionAuth")
.Requirements.Add(new HasArranqueInactivoRequirement()
));
options.AddPolicy("IsParagemNotOnGoing", policy =>
policy.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ProductionAuth")
.Requirements.Add(new IsParagemNotOnGoingRequirement()
));
options.AddPolicy("IsParagemOnGoing", policy =>
policy.RequireAuthenticatedUser()
.AddAuthenticationSchemes("ProductionAuth")
.Requirements.Add(new IsParagemOnGoingRequirement()
));
});
services.AddMemoryCache();
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Administration", "/Account");
options.Conventions.AuthorizeAreaFolder("Production", "/Account");
})
.AddNToastNotifyToastr(new ToastrOptions()
{
ProgressBar = true,
TimeOut = 3000,
PositionClass = ToastPositions.TopFullWidth,
PreventDuplicates = true,
TapToDismiss = true
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseNToastNotify();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
这是我的处理程序,每个处理程序基本相同。要求很空洞, body 里什么都没有。
public class IsParagemNotOnGoingHandler : AuthorizationHandler<IsParagemNotOnGoingRequirement>
{
private readonly DatabaseContext _context;
public IsParagemNotOnGoingHandler(DatabaseContext context)
{
_context = context;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsParagemNotOnGoingRequirement requirement)
{
// Get the context
var redirectContext = context.Resource as AuthorizationFilterContext;
var registoId = Convert.ToInt32(context.User.FindFirst(c => c.Type == ClaimTypes.PrimarySid).Value);
bool IsRegistoOnGoing = _context.ParagensRegistos.Any(pr => pr.RegistoId == registoId && pr.HoraFim == null);
if (!IsRegistoOnGoing)
{
context.Succeed(requirement);
}
else
{
redirectContext.Result = new RedirectToPageResult("/Paragem");
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
这是个异常(exception)
An unhandled exception occurred while processing the request. NullReferenceException: Object reference not set to an instance of an object. NoPaper.Policies.IsParagemNotOnGoingHandler.HandleRequirementAsync(AuthorizationHandlerContext context, IsParagemNotOnGoingRequirement requirement) in IsParagemNotOnGoingHandler.cs, line 27
Stack Query Cookies Headers NullReferenceException: Object reference not set to an instance of an object. NoPaper.Policies.IsParagemNotOnGoingHandler.HandleRequirementAsync(AuthorizationHandlerContext context, IsParagemNotOnGoingRequirement requirement) in IsParagemNotOnGoingHandler.cs + var registoId = Convert.ToInt32(context.User.FindFirst(c => c.Type == ClaimTypes.PrimarySid).Value); Microsoft.AspNetCore.Authorization.AuthorizationHandler.HandleAsync(AuthorizationHandlerContext context) Microsoft.AspNetCore.Authorization.DefaultAuthorizationService.AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements) Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource) Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.OnAuthorizationAsync(AuthorizationFilterContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) NToastNotify.NtoastNotifyAjaxToastsMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass5_1+<b__1>d.MoveNext() Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
最佳答案
docs 中有一条重要说明解决这个问题:
Authorization handlers are called even if authentication fails.
在您的情况下,身份验证失败但您的 IsParagemNotOnGoingHandler
的 HandleRequirementAsync
仍在调用。要解决此问题,您只需让您的处理程序实现对丢失的声明更具弹性。这是完整性的示例:
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsParagemNotOnGoingRequirement requirement)
{
if (!context.User.HasClaim(c => c.Type == ClaimTypes.PrimarySid))
return Task.CompletedTask;
...
}
对于声明的值不可转换为 int
的情况,您可能还想防止 Convert.ToInt32
失败。
关于c# - Asp .Net Core 为什么即使用户未通过身份验证也会调用我的授权处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56806054/