ConfigureServices在类的方法中考虑以下代码Startup-
services.AddTransient<IAuthorizationHandler, BlockUsersHandler>();
services.AddTransient<IAuthorizationHandler, BlockClaimHandler>();
services.AddAuthorization(option =>
{
option.AddPolicy("NotHacker", policy =>
{
policy.AddRequirements(new BlockUsersRequirement("Hacker"));
});
option.AddPolicy("NotThatClaim", policy =>
{
policy.AddRequirements(new BlockClaimRequirement(new Claim("ThatClaimType", "ThatClaim")));
});
});
这些是自定义类实现 -
public class BlockUsersRequirement : IAuthorizationRequirement
{
// Code goes here
}
public class BlockUsersHandler : AuthorizationHandler<BlockUsersRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BlockUsersRequirement requirement)
{
// Code goes here
}
}
public class BlockClaimRequirement : IAuthorizationRequirement
{
// Code goes here
}
public class BlockClaimHandler : AuthorizationHandler<BlockClaimRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BlockClaimRequirement requirement)
{
// Code goes here
}
}
我的理解是,每当遇到对服务的依赖时,内置的依赖解析器都会提供为该服务注册的具体实现,如果我注册了一个服务的多个实现,那么最后一次注册就会生效。
在上面的代码中,注册了两个实现IAuthorizationHandler,两个授权策略都可以正常工作。
那么,依赖解析器如何决定何时选择哪个实现呢?并且基于什么?
编辑 - 2019.07.28
因此,正如@Martin 在下面回答的那样,看起来依赖解析器可以从 Handler 实现派生的IAuthorizationRequirement中推断出实现。AuthorizationHandler<TRequirement>
但是您实际上可以通过直接实现IAuthorizationHandler接口来创建一个 Handler 类,而无需派生AuthorizationHandler<TRequirement>-
public class DeletePermissionRequirement : IAuthorizationRequirement
{
// Nothing here
}
public class DeletePermissionHandler : IAuthorizationHandler
{
public Task HandleAsync(AuthorizationHandlerContext context)
{
// Code goes here
}
}
因此,现在IAuthorizationRequirement处理程序的签名中没有可以推断的内容。
此外,您可以为单个需求添加多个 Handler 实现 -
public class BuildingEntryRequirement : IAuthorizationRequirement
{
// Nothing here
}
public class BadgeEntryHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
{
// Code goes here
}
}
public class TemporaryPassHandler : AuthorizationHandler<BuildingEntryRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BuildingEntryRequirement requirement)
{
// Code goes here
}
}
考虑到这些新的实现,ConfigureServices方法中的代码看起来像 -
services.AddTransient<IAuthorizationHandler, BlockUsersHandler>();
services.AddTransient<IAuthorizationHandler, BlockClaimHandler>();
services.AddTransient<IAuthorizationHandler, DeletePermissionHandler>();
services.AddTransient<IAuthorizationHandler, BadgeEntryHandler>();
services.AddTransient<IAuthorizationHandler, TemporaryPassHandler>();
services.AddAuthorization(option =>
{
option.AddPolicy("NotHacker", policy =>
{
policy.AddRequirements(new BlockUsersRequirement("Hacker"));
});
option.AddPolicy("NotThatClaim", policy =>
{
policy.AddRequirements(new BlockClaimRequirement(new Claim("ThatClaimType", "ThatClaim")));
});
option.AddPolicy("CanDelete", policy =>
{
policy.AddRequirements(new DeletePermissionRequirement());
});
option.AddPolicy("BadgeEntry", policy =>
{
policy.AddRequirements(new BuildingEntryRequirement());
});
});
当然,所有授权策略都运行良好。
再说一遍,依赖解析器是如何选择正确的实现的?