Luk*_*988 10 c# authentication dependency-injection asp.net-web-api .net-core
我将 .NET Core WebAPI 与依赖项注入和多个身份验证模式(http 基本、访问密钥、JWT)结合使用。我注入了一些需要一些经过身份验证的用户数据的业务服务。如果用户通过任何 auth 中间件进行身份验证,DI 工作正常。如果用户未通过身份验证,DI 将无法解析某些服务。我需要 DI 返回null
。
这怎么可能?下面的代码将导致异常,null
不允许作为结果。
services.AddTransient<IMasterRepository>(serviceProvider =>
{
var _serviceFactory = new RepositoriesFactory(Configuration);
if (!Authenticated)
{
return null;
}
return _serviceFactory.CreateMasterRepository();
});
Run Code Online (Sandbox Code Playgroud)
另外,我无法在身份验证中间件中返回 401,因为另一个中间件可能会成功(expl:无法在 http 基本身份验证中间件中返回 401,因为下一个 JWT 可能会成功)
此外,我无法在所有身份验证中间件之后添加“需要身份验证”检查,因为某些控制器是公共的(不需要身份验证/依赖项注入)。
有什么建议吗?谢谢!
默认 DI 框架在设计上不允许工厂委托返回 null。
通过创建从接口派生的 NullObject 来考虑空对象模式
public class NullRepository : IMasterRepository {
public static readonly IMasterRepository Empty = new NullRepository();
public NullRepository () { }
//...implement members that do nothing and may return empty collections.
}
Run Code Online (Sandbox Code Playgroud)
调用时不执行任何操作。
services.AddTransient<IMasterRepository>(serviceProvider => {
IMasterRepository result = NullRepository.Empty;
var _serviceFactory = new RepositoriesFactory(Configuration);
if (Authenticated) {
result = _serviceFactory.CreateMasterRepository();
}
return result;
});
Run Code Online (Sandbox Code Playgroud)
检查 null 现在变为
//ctor
public SomeClass(IMasterRepository repository) {
if(repository == NullRepository.Empty)
//...throw
//...
}
Run Code Online (Sandbox Code Playgroud)
有没有在任何问题登记的执行情况null
。只有解决了才会有问题。
换句话说,如果您注册:
services.AddTransient<IMasterRepository>(provider => null);
Run Code Online (Sandbox Code Playgroud)
然后尝试:
private readonly IMasterRepository _repository;
public SomeController(IMasterRepository repository)
{
_repository = repository;
}
Run Code Online (Sandbox Code Playgroud)
您将InvalidOperationException
在运行时收到一个类似以下内容的消息:
尝试激活“MyApp.Controllers.SomeController”时无法解析“MyApp.IMasterRepository”类型的服务
但是,有一个简单的解决方法。不是注入接口,而是注入该接口的一个IEnumerable
:
private readonly IMasterRepository _repository;
public SomeController(IEnumerable<IMasterRepository> repositories)
{
_repository = repositories.First(); // (using System.Linq)
}
Run Code Online (Sandbox Code Playgroud)
您可能认为它应该是FirstOrDefault
,但是确实会有一个包含null
您注册的项目。
这种方法之所以有效,是因为 ASP.Net Core 中的 DI 支持注册给定类型的多个实现,null
并且在注册时不区分和 对象实例。
请记住,即使这样可行,也不建议这样做,因为现在该_repository
变量可能为空,并且每次访问时都必须使用空检查。例如:if (_repository != null) { _repository.DoSomething(); }
或_repository?.DoSomething();
。大多数人不希望编写那样的代码。
这涵盖了问题的 DI 部分。但是,如果问题确实出在 auth 上,那么ste-fu 的回答描述了一种更合适的方法。
归档时间: |
|
查看次数: |
4314 次 |
最近记录: |