gpt4 book ai didi

c# - AuthorizationHandler 异常不通过 ExceptionFilter

转载 作者:太空宇宙 更新时间:2023-11-03 23:13:16 26 4
gpt4 key购买 nike

我在 ASP.NET Core MVC (dnx46) RC1 中有一个带有 AuthorizationHandler 的应用程序:

public class AppSumAuthAuthorizationHandler : AuthorizationHandler<AppSumAuthRequirement>
{
private readonly IUserRepository _userRepository;
private readonly IUserRoleRepository _userRoleRepository;

public AppSumAuthAuthorizationHandler(IUserRepository userRepository, IUserRoleRepository userRoleRepository)
{
_userRepository = userRepository;
_userRoleRepository = userRoleRepository;
}
protected override async void Handle(AuthorizationContext context, AppSumAuthRequirement requirement)
{
await HandleAsync(context,requirement);
}

protected override async Task HandleAsync(AuthorizationContext context, AppSumAuthRequirement requirement)
{
var currentUserName = context.User.Identity.Name;
var currentUser = await _userRepository.GetAsync(u => u.UserName == context.User.Identity.Name);

// Create user that does not yet exist
if(currentUser == null)
{
var user = new User(currentUserName);
/* Temporary add SysAdmin role */
using(new CreatedBySystemProvider(_userRepository))
{
_userRepository.Add(user);
await _userRepository.SaveChangesAsync();
if (string.Equals(currentUserName, @"BIJTJES\NilsG", StringComparison.CurrentCultureIgnoreCase))
{
user.AddRole(1);
}
currentUser = await _userRepository.GetAsync(u => u.Id == user.Id);
}
}
var resource = (Microsoft.AspNet.Mvc.Filters.AuthorizationContext) context.Resource;
var controllerActionDescriptor = resource.ActionDescriptor as ControllerActionDescriptor;
var controllerName = controllerActionDescriptor.ControllerName;
var actionName = controllerActionDescriptor.Name;
string moduleName;
try
{
// Get the name of the module
moduleName = ((ModuleAttribute)controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(false).First(a => a.GetType().Name == "ModuleAttribute")).ModuleName;
}
catch(InvalidOperationException ex)
{
context.Fail();
throw new InvalidOperationException($"The Module Attribute is required on basecontroller {controllerName}.", ex);
}

var access = new Access(moduleName, controllerName, actionName);

if (await currentUser.HasPermissionTo(UrlAccessLevel.Access).OnAsync(access))
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
}
}

需求类为空:

public interface IAppSumAuthRequirement : IAuthorizationRequirement
{

}
public class AppSumAuthRequirement : IAppSumAuthRequirement
{

}

Module 属性也没什么特别的:

public class ModuleAttribute : Attribute
{
public string ModuleName { get; private set; }
public ModuleAttribute(string moduleName)
{
ModuleName = moduleName;
}

public override string ToString()
{
return ModuleName;
}
}

异常过滤器:

    public class JsonExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
var exception = context.Exception;
context.HttpContext.Response.StatusCode = 500;
context.Result = new JsonResult(new Error
{
Message = exception.Message,
InnerException = exception.InnerException?.InnerException?.Message,
Data = exception.Data,
ErrorCode = exception.HResult,
Source = exception.Source,
Stacktrace = exception.StackTrace,
ErrorType = exception.GetType().ToString()
});
}
}

策略在我的 Startup.cs 中配置:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(new JsonExceptionFilterAttribute());
options.ModelBinders.Insert(0, new NullableIntModelBinder());
}).AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
});

// Security
services.AddAuthorization(options =>
{
options.AddPolicy("AppSumAuth",
policy => policy.Requirements.Add(new AppSumAuthRequirement()));
});
}

并且通过继承BaseController在所有 Controller 上设置策略:

[Authorize(Policy = "AppSumAuth")]
public class BaseController : Controller
{
public BaseController()
{

}
}

因此,在我的处理程序中,我获得了 Controller 名称、操作名称和模块名称(来自 Controller 上设置的属性):

[Module("Main")]

当此属性未在 Controller 上设置时,我想捕获异常并将此报告回调用 Controller 的开发人员并拒绝访问。为此,我添加了:

        catch(InvalidOperationException ex)
{
context.Fail();
throw new InvalidOperationException($"The Module Attribute is required on basecontroller {controllerName}.", ex);
}

当 Controller 出现异常时,JsonExceptionFilter 被完美调用。但是,当 AuthorizationHandler 中出现错误时,它不会被调用。


所以问题:

如何让 JsonExceptionFilter 捕获异常?我做错了什么?

解决方案:

启动.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// For Windows Auth!
app.UseIISPlatformHandler();

app.UseStaticFiles();

app.UseExceptionHandler(AppSumExceptionMiddleware.JsonHandler());

app.UseMvc();
}

还有我的中间件:

public class AppSumExceptionMiddleware
{
public static Action<IApplicationBuilder> JsonHandler()
{
return errorApp =>
{
errorApp.Run(async context =>
{
var exception = context.Features.Get<IExceptionHandlerFeature>();
if (exception != null)
{
var exceptionJson = Encoding.UTF8.GetBytes(
JsonConvert.SerializeObject(new AppSumException(exception.Error),
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
})
);
context.Response.ContentType = "application/json";
await context.Response.Body.WriteAsync(exceptionJson, 0, exceptionJson.Length);
}
});
};
}
}

最佳答案

Action 过滤器可以用作方法过滤器、 Controller 过滤器或全局过滤器,仅适用于 MVC HTTP 请求。在您的情况下,您需要使用 middleware , 作为

Middleware is component that "sit" on the HTTP pipeline and examine all requests and responses.

因为你想在异常(exception)情况下工作,你可以使用现成的 ExceptionHandler中间件:

        app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500; // for example

var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
var ex = error.Error;
// custom logic
}
});
});

关于c# - AuthorizationHandler 异常不通过 ExceptionFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38199728/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com