我有一个Asp.Net Core 1 RC1
应用程序,它使用自定义路由约束来控制对应用程序的访问。应用程序(托管在运行IIS 7.5
的服务器上)正在获得间歇性的404错误,我怀疑这是由此路由约束引起的。在这里,您可以看到显示间歇性404错误的屏幕截图:
我怀疑此问题与定义路由约束不是线程安全的代码有关。自定义路由约束需要DbContext
,因为如果为路由中指定的品牌启用了应用程序,则需要检入数据库,并且我怀疑此DbContext
实例可能导致该问题。以下是在应用程序中定义路由的方法:
// Add MVC to the request pipeline.
var appDbContext = app.ApplicationServices.GetRequiredService<AppDbContext>();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "branding",
template: "branding/{brand}/{controller}/{action}/{id?}",
defaults: new { controller="Home", action="Index" },
constraints: new { brand = new BrandingRouteConstraint(appDbContext) });
});
这是自定义路线约束:
// Custom route constraint
public class BrandingRouteConstraint : IRouteConstraint
{
AppDbContext _appDbContext;
public BrandingRouteConstraint(AppDbContext appDbContext) : base() {
_appDbContext = appDbContext;
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey, IDictionary<string, object> values, RouteDirection routeDirection)
{
if (values.Keys.Contains(routeKey))
{
var whiteLabel = _appDbContext.WhiteLabels.Where(w => w.Url == values[routeKey].ToString()).FirstOrDefault();
if (whiteLabel != null && whiteLabel.EnableApplication != null && (bool)whiteLabel.EnableApplication)
{
return true;
}
}
return false;
}
}
任何人都可以确认此问题是由代码不是线程安全引起的,并建议一种更改实现的方法,以便它是线程安全的吗?
答案 0 :(得分:1)
我无法对RouteContraint进行评论,还没有使用它们,但您是否尝试过基于资源的授权?看起来它可能更适合您尝试实现的目标?
在控制器内请求身份验证服务
public class DocumentController : Controller
{
IAuthorizationService authorizationService;
public DocumentController(IAuthorizationService authorizationService)
{
this.authorizationService = authorizationService;
}
}
在您的操作中应用授权检查:
public async Task<IActionResult> Edit(Guid documentId)
{
Document document = documentRepository.Find(documentId);
if (document == null)
{
return new HttpNotFoundResult();
}
if (await authorizationService.AuthorizeAsync(User, document, Operations.Edit))
{
return View(document);
}
else
{
return new HttpUnauthorizedResult();
}
}
我在示例中使用了OperationAuthorizationRequirement类,因此在项目中定义此类:
public static class Operations
{
public static OperationAuthorizationRequirement Create =
new OperationAuthorizationRequirement { Name = "Create" };
public static OperationAuthorizationRequirement Read =
new OperationAuthorizationRequirement { Name = "Read" };
public static OperationAuthorizationRequirement Update =
new OperationAuthorizationRequirement { Name = "Update" };
public static OperationAuthorizationRequirement Delete =
new OperationAuthorizationRequirement { Name = "Delete" };
}
实现授权处理程序(使用内置的OperationAuthorizationRequirement要求):
public class DocumentAuthorizationHandler : AuthorizationHandler<OperationAuthorizationRequirement, Document>
{
protected override void Handle(AuthorizationContext context,
OperationAuthorizationRequirement requirement,
Document resource)
{
// Validate the requirement against the resource and identity.
// Sample just checks "Name"field, put your real logic here :)
if (resource.Name == "Doc1")
context.Succeed(requirement);
else
context.Fail();
}
}
不要忘记ConfigureServices:
services.AddInstance<IAuthorizationHandler>(
new DocumentAuthorizationHandler());
它的工作量更多,但增加了很多灵活性。