c# - 在类中实例化 IConfidentialClientApplication 是不好的做法吗?
问题描述
例如,我AuthorizationClient
在我的应用程序配置中注册了一个临时服务,它充当我的 API 和 Azure 之间的授权令牌的客户端中介。在里面,有一个 IConfidentialClientApplication
对象属性:
public class AuthorizationClient : IAuthorizationClient
{
private readonly string[] _resourceIds;
private IConfidentialClientApplication App;
public AuthorizationClient(IAuthenticationConfig AuthenticationConfig, IConfiguration configuration)
{
var scope = "/.default";
var resourceId = "api://" + configuration[AuthenticationConfig.ResourceID] + scope;
var clientId = configuration[AuthenticationConfig.ClientID];
var clientSecret = configuration[AuthenticationConfig.ClientSecret];
var instance = AuthenticationConfig.Instance;
var tenant = configuration[AuthenticationConfig.AzureTenantId];
var authority = string.Format(CultureInfo.InvariantCulture, instance, tenant);
_resourceIds = new string[] { resourceId };
try
{
App = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri(authority))
.Build();
}
catch(Exception ex)
{
//TODO logger
}
}
...
}
在这个类的其他地方,我有成功获取令牌、检查令牌缓存等的方法。
但是当我看到IConfidentialClientApplication
正在使用的文档或存储库时,它总是在应用程序级别作为服务添加,而不是在另一个对象中。我这样做的方式是否存在潜在的陷阱?
IConfidentialClientApplication
如果每个客户端请求都实例化一个新的,这似乎相当重/大,但是当我在一个应用级服务的对象中实例化它时,每个生命周期似乎只创建一个。
解决方案
在目标类中实例化依赖是一种代码味道
陷阱:与实现细节的紧密耦合和显式依赖原则违规。
这些将使孤立地维护和测试您的课程变得困难。
通过应用单一责任原则/关注点分离和显式依赖原则,可以修复这些设计问题,使您的代码更加可靠
创建一个类来存储客户端选项。根据提供的示例,它可能看起来像这样
public class AuthorizationClientOptions {
public string[] ResourceIds { get; set; }
}
重构类以显式依赖于它实际需要什么来执行其功能
public class AuthorizationClient : IAuthorizationClient {
private readonly string[] _resourceIds;
private readonly IConfidentialClientApplication app;
public AuthorizationClient(IConfidentialClientApplication app, IOptions<AuthorizationClientOptions> options) {
this.app = app;
_resourceIds = options.Value.ResourceIds;
}
// ...
}
在组合根中配置必要的实现细节(启动)
//...
IConfiguration Configuration; //Populated either via constructor injection or manually
public void ConfigureServices(IServiceCollection services) {
//...
//Configure options
services.AddOptions<AuthorizationClientOptions>()
.Configure<IAuthenticationConfig,IConfiguration>(
(o, authConfig, config) => {
var scope = "/.default";
var resourceId = "api://" + config[authConfig.ResourceID] + scope;
o.ResourceIds = new string[] { resourceId };
});
//Configure dependency using factory delegate
services.AddSingleton<IConfidentialClientApplication>(sp => {
IAuthenticationConfig AuthenticationConfig = sp.GetRequiredService<IAuthenticationConfig>();
var instance = Configuration.Instance;
var tenant = Configuration[AuthenticationConfig.AzureTenantId];
var authority = string.Format(CultureInfo.InvariantCulture, instance, tenant);
var clientId = Configuration[AuthenticationConfig.ClientID];
var clientSecret = Configuration[AuthenticationConfig.ClientSecret];
return ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri(authority))
.Build();
});
services.AddScoped<IAuthorizationClient, AuthorizationClient>();
//...
}
IConfidentialClientApplication
如果每个客户端请求都实例化一个新的,这似乎相当重/大
上面示例中的IConfidentialClientApplication
是作为单例创建的,因此在实例化时将具有一次性成本。
推荐阅读
- react-native - 如何使用“react-native-android-pip”?
- android - 弹出菜单在屏幕上显示为空白
- c - 在 platform_driver 的探测函数中,dev.of_node 始终为 NULL
- javascript - ReactJS - 在表单上单击另一个选项后如何重新渲染组件?
- c# - c#中的多个错误无法解决
- python - ValueError:输入包含 NaN、无穷大或对于线性回归中的 dtype('float64') 而言太大的值
- mysql - 为什么 Sqlalchemy Flask 中仍显示已删除的数据?
- swift - 有没有办法只使用像素数据指针而不使用 CVPixelBuffer 来制作 MTLTexture?
- javascript - 如何将数字 API 输入为字符串或我将在哪里放置 toString()
- css - 离子如何将离子含量与页面底部对齐