feat(DirectorySearchService): Validierungs-Methode für Anmeldeinformationen hinzugefügt
- Neue Methode zur Überprüfung von Anmeldeinformationen in DirectorySearchService hinzugefügt. - Anpassung der Eigenschaften von Suchergebnissen ermöglicht.
This commit is contained in:
@@ -55,12 +55,6 @@ namespace DigitalData.Core.Application
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddDirectoryService(this IServiceCollection service)
|
||||
{
|
||||
service.AddScoped<IDirectoryService, DirectoryService>();
|
||||
return service;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddDirectorySearchService(this IServiceCollection service)
|
||||
{
|
||||
service.AddMemoryCache();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using DigitalData.Core.Contracts.Application;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Configuration;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.DirectoryServices;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
|
||||
namespace DigitalData.Core.Application
|
||||
{
|
||||
@@ -12,15 +12,39 @@ namespace DigitalData.Core.Application
|
||||
public class DirectorySearchService : ServiceBase, IDirectorySearchService
|
||||
{
|
||||
private readonly IMemoryCache _memoryCache;
|
||||
public readonly string SearchRootPath;
|
||||
public string ServerName { get; }
|
||||
public string Root { get; }
|
||||
public string SearchRootPath { get; }
|
||||
private readonly DateTimeOffset _userCacheExpiration;
|
||||
public Dictionary<string, string> CustomSearchFilters { get; }
|
||||
|
||||
public DirectorySearchService(IConfiguration configuration, ILogger<DirectoryService> logger, IMemoryCache memoryCache)
|
||||
public DirectorySearchService(IConfiguration configuration, ILogger<DirectorySearchService> logger, IMemoryCache memoryCache)
|
||||
{
|
||||
SearchRootPath = configuration["DirectorySearch:SearchRootPath"] ?? throw new ConfigurationErrorsException("SearchRootPath configuration is missing.");
|
||||
_memoryCache = memoryCache;
|
||||
|
||||
ServerName = configuration["DirectorySearch:ServerName"] ?? throw new InvalidOperationException("The server name for directory search is not configured. Please specify the 'DirectorySearch:ServerName' in the configuration.");
|
||||
|
||||
Root = configuration["DirectorySearch:Root"] ?? throw new InvalidOperationException("The root for directory search is not configured. Please specify the 'DirectorySearch:Root' in the configuration.");
|
||||
|
||||
SearchRootPath = $"LDAP://{ServerName}/{Root}";
|
||||
|
||||
var customSearchFiltersSection = configuration.GetSection("DirectorySearch:CustomSearchFilters");
|
||||
CustomSearchFilters = customSearchFiltersSection.Get<Dictionary<string, string>>() ?? new();
|
||||
|
||||
var dayCounts = configuration.GetValue<int>("DirectorySearch:UserCacheExpirationDays");
|
||||
if (dayCounts == default)
|
||||
_userCacheExpiration = default;
|
||||
else
|
||||
_userCacheExpiration = DateTimeOffset.Now.Date.AddDays(dayCounts);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000)
|
||||
public bool ValidateCredentials(string dirEntryUsername, string dirEntryPassword)
|
||||
{
|
||||
using var context = new PrincipalContext(ContextType.Domain, ServerName, Root);
|
||||
return context.ValidateCredentials(dirEntryUsername, dirEntryPassword);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAll(DirectoryEntry searchRoot, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
|
||||
{
|
||||
List<ResultPropertyCollection> list = new();
|
||||
|
||||
@@ -32,6 +56,14 @@ namespace DigitalData.Core.Application
|
||||
SearchRoot = searchRoot
|
||||
};
|
||||
|
||||
if (properties.Length > 0)
|
||||
{
|
||||
searcher.PropertiesToLoad.Clear();
|
||||
foreach (var property in properties)
|
||||
if(property is not null)
|
||||
searcher.PropertiesToLoad.Add(property);
|
||||
}
|
||||
|
||||
foreach (SearchResult result in searcher.FindAll())
|
||||
{
|
||||
ResultPropertyCollection rpc = result.Properties;
|
||||
@@ -41,7 +73,7 @@ namespace DigitalData.Core.Application
|
||||
return Successful<IEnumerable<ResultPropertyCollection>>(list);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000)
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> FindAllByUserCache(string username, string filter, SearchScope searchScope = SearchScope.Subtree, int sizeLimit = 5000, params string[] properties)
|
||||
{
|
||||
List<ResultPropertyCollection> list = new();
|
||||
|
||||
@@ -50,7 +82,21 @@ namespace DigitalData.Core.Application
|
||||
if (searchRoot is null)
|
||||
return Failed<IEnumerable<ResultPropertyCollection>>(MessageKey.DirSearcherDisconnected.ToString());
|
||||
|
||||
return FindAll(searchRoot, filter, searchScope, sizeLimit);
|
||||
return FindAll(searchRoot, filter, searchScope, sizeLimit, properties);
|
||||
}
|
||||
|
||||
public void SetSearchRootCache(string dirEntryUsername, string dirEntryPassword)
|
||||
{
|
||||
if (_userCacheExpiration == default)
|
||||
_memoryCache.Set(key: dirEntryUsername, new DirectoryEntry(path: SearchRootPath, username: dirEntryUsername, password: dirEntryPassword));
|
||||
else
|
||||
_memoryCache.Set(key: dirEntryUsername, new DirectoryEntry(path: SearchRootPath, username: dirEntryUsername, password: dirEntryPassword), absoluteExpiration: _userCacheExpiration);
|
||||
}
|
||||
|
||||
public DirectoryEntry? GetSearchRootCache(string dirEntryUsername)
|
||||
{
|
||||
_memoryCache.TryGetValue(dirEntryUsername, out DirectoryEntry? root);
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Contracts.Application;
|
||||
using System.DirectoryServices;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Configuration;
|
||||
|
||||
namespace DigitalData.Core.Application
|
||||
{
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public class DirectoryService : ServiceBase, IDirectoryService
|
||||
{
|
||||
protected IMapper _mapper;
|
||||
protected readonly DirectorySearcher _groupSearcher;
|
||||
IConfiguration _configuration;
|
||||
|
||||
public readonly string SearchRootPath;
|
||||
|
||||
public DirectoryService(IMapper mapper, IConfiguration configuration, ILogger<DirectoryService> logger) {
|
||||
_mapper = mapper;
|
||||
_configuration = configuration;
|
||||
|
||||
var searchRoot = configuration["DirectorySearch:SearchRootPath"];
|
||||
|
||||
logger.LogInformation($"Search Root is {searchRoot}.");
|
||||
|
||||
SearchRootPath = _configuration["DirectorySearch:SearchRootPath"] ?? throw new ConfigurationErrorsException("SearchRootPath configuration is missing.");
|
||||
|
||||
_groupSearcher = new DirectorySearcher()
|
||||
{
|
||||
Filter = "(&(objectClass=group) (samAccountName=*))",
|
||||
SearchScope = SearchScope.Subtree,
|
||||
SizeLimit = 5000,
|
||||
SearchRoot = new DirectoryEntry(searchRoot)
|
||||
};
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> ReadAllGroupAsCollection()
|
||||
{
|
||||
List<ResultPropertyCollection> list = new();
|
||||
|
||||
foreach (SearchResult result in _groupSearcher.FindAll())
|
||||
{
|
||||
ResultPropertyCollection rpc = result.Properties;
|
||||
list.Add(rpc);
|
||||
}
|
||||
|
||||
return Successful<IEnumerable<ResultPropertyCollection>>(list);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<ResultPropertyCollection>> ReadAllGroupAsCollection(string serverAddress, string username, string password)
|
||||
{
|
||||
var searcher = new DirectorySearcher()
|
||||
{
|
||||
Filter = "(&(objectClass=user)(sAMAccountName=*))",
|
||||
SearchScope = SearchScope.Subtree,
|
||||
SizeLimit = 5000,
|
||||
SearchRoot = new DirectoryEntry($"LDAP://{serverAddress}/DC=dd-gan,DC=local,DC=digitaldata,DC=works", username, password)
|
||||
};
|
||||
|
||||
List<ResultPropertyCollection> list = new();
|
||||
|
||||
foreach (SearchResult result in searcher.FindAll())
|
||||
{
|
||||
ResultPropertyCollection rpc = result.Properties;
|
||||
list.Add(rpc);
|
||||
}
|
||||
|
||||
return Successful<IEnumerable<ResultPropertyCollection>>(list);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<Dictionary<string, object>>> ReadGroupByPropertyName(string propertyName = "samaccountname")
|
||||
{
|
||||
List<Dictionary<string, object>> list = new();
|
||||
|
||||
foreach (SearchResult result in _groupSearcher.FindAll())
|
||||
{
|
||||
var value = result.Properties[propertyName];
|
||||
if (value is not null)
|
||||
list.Add(new Dictionary<string, object>()
|
||||
{
|
||||
[propertyName] = value
|
||||
});
|
||||
}
|
||||
|
||||
return Successful<IEnumerable<Dictionary<string, object>>>(list);
|
||||
}
|
||||
|
||||
public IServiceResult<IEnumerable<UserPrincipalDto>> ReadUserByGroup<UserPrincipalDto>(string groupIdentityValue, IdentityType groupIdentityType = IdentityType.Name, bool recursive = true)
|
||||
{
|
||||
List<UserPrincipalDto> upDTOs = new();
|
||||
|
||||
using PrincipalContext context = new(ContextType.Domain);
|
||||
using GroupPrincipal? groupPrincipal = GroupPrincipal.FindByIdentity(context, groupIdentityType, groupIdentityValue);
|
||||
|
||||
if (groupPrincipal is null)
|
||||
return Failed<IEnumerable<UserPrincipalDto>>();
|
||||
|
||||
using PrincipalSearchResult<Principal> principalSearchResult = groupPrincipal.GetMembers(recursive);
|
||||
|
||||
foreach (Principal principal in principalSearchResult)
|
||||
{
|
||||
if (principal is UserPrincipal userPrincipal)
|
||||
{
|
||||
var upDto = _mapper.MapOrThrow<UserPrincipalDto>(userPrincipal);
|
||||
upDTOs.Add(upDto);
|
||||
}
|
||||
}
|
||||
|
||||
return Successful<IEnumerable<UserPrincipalDto>>(upDTOs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll": {
|
||||
"assemblyVersion": "7.0.0.0",
|
||||
"fileVersion": "7.0.423.11508"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection/7.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0"
|
||||
@@ -327,6 +338,7 @@
|
||||
"DigitalData.Core.Contracts/1.0.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Caching.Memory": "7.0.0",
|
||||
"Microsoft.Extensions.Configuration.Binder": "7.0.4",
|
||||
"System.DirectoryServices": "7.0.1",
|
||||
"System.DirectoryServices.AccountManagement": "7.0.1"
|
||||
},
|
||||
@@ -377,6 +389,13 @@
|
||||
"path": "microsoft.extensions.configuration.abstractions/7.0.0",
|
||||
"hashPath": "microsoft.extensions.configuration.abstractions.7.0.0.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
"sha512": "sha512-8+XPvJnHZsYgHOQlcMuQe7QNF5KdVKHH1F/wW3nd8/u81Gk/XFAYMDP0Lpz18h7/AM95M662vvqMorcYxCBB4w==",
|
||||
"path": "microsoft.extensions.configuration.binder/7.0.4",
|
||||
"hashPath": "microsoft.extensions.configuration.binder.7.0.4.nupkg.sha512"
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection/7.0.0": {
|
||||
"type": "package",
|
||||
"serviceable": true,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
d6b492d4d707f47dd6268572d14db639b2b8036b
|
||||
27b4d1c0e521dbdcdae7e49ff5b85233b84a7ece
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -147,6 +147,10 @@
|
||||
"target": "Package",
|
||||
"version": "[7.0.0, )"
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder": {
|
||||
"target": "Package",
|
||||
"version": "[7.0.4, )"
|
||||
},
|
||||
"System.DirectoryServices": {
|
||||
"target": "Package",
|
||||
"version": "[7.0.1, )"
|
||||
|
||||
@@ -99,6 +99,25 @@
|
||||
"buildTransitive/net6.0/_._": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "7.0.0"
|
||||
},
|
||||
"compile": {
|
||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll": {
|
||||
"related": ".xml"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"buildTransitive/net6.0/_._": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection/7.0.0": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
@@ -452,6 +471,7 @@
|
||||
"framework": ".NETCoreApp,Version=v7.0",
|
||||
"dependencies": {
|
||||
"Microsoft.Extensions.Caching.Memory": "7.0.0",
|
||||
"Microsoft.Extensions.Configuration.Binder": "7.0.4",
|
||||
"System.DirectoryServices": "7.0.1",
|
||||
"System.DirectoryServices.AccountManagement": "7.0.1"
|
||||
},
|
||||
@@ -588,6 +608,33 @@
|
||||
"useSharedDesignerContext.txt"
|
||||
]
|
||||
},
|
||||
"Microsoft.Extensions.Configuration.Binder/7.0.4": {
|
||||
"sha512": "8+XPvJnHZsYgHOQlcMuQe7QNF5KdVKHH1F/wW3nd8/u81Gk/XFAYMDP0Lpz18h7/AM95M662vvqMorcYxCBB4w==",
|
||||
"type": "package",
|
||||
"path": "microsoft.extensions.configuration.binder/7.0.4",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"Icon.png",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"buildTransitive/net461/Microsoft.Extensions.Configuration.Binder.targets",
|
||||
"buildTransitive/net462/_._",
|
||||
"buildTransitive/net6.0/_._",
|
||||
"buildTransitive/netcoreapp2.0/Microsoft.Extensions.Configuration.Binder.targets",
|
||||
"lib/net462/Microsoft.Extensions.Configuration.Binder.dll",
|
||||
"lib/net462/Microsoft.Extensions.Configuration.Binder.xml",
|
||||
"lib/net6.0/Microsoft.Extensions.Configuration.Binder.dll",
|
||||
"lib/net6.0/Microsoft.Extensions.Configuration.Binder.xml",
|
||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.dll",
|
||||
"lib/net7.0/Microsoft.Extensions.Configuration.Binder.xml",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll",
|
||||
"lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.xml",
|
||||
"microsoft.extensions.configuration.binder.7.0.4.nupkg.sha512",
|
||||
"microsoft.extensions.configuration.binder.nuspec",
|
||||
"useSharedDesignerContext.txt"
|
||||
]
|
||||
},
|
||||
"Microsoft.Extensions.DependencyInjection/7.0.0": {
|
||||
"sha512": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==",
|
||||
"type": "package",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "QbFi3Bjc6Jq5Z4fakBzuNU7pNttdG/DCmVVyuo9l0kz0AbeYFlsb08iiLxlvwMAW4Yiq7Puor/g1fVXD9WndbQ==",
|
||||
"dgSpecHash": "n93+MKQABba3OlvV9vsNTsnfi5nHWhj3CavVgX3I9I1+zCwApoWk5yls2KENGsGobTCWb/ng+KmBQYYwtkP9AA==",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\TekH\\Visual Studio\\WebCoreModules\\DigitalData.Core.Application\\DigitalData.Core.Application.csproj",
|
||||
"expectedPackageFiles": [
|
||||
@@ -9,6 +9,7 @@
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.caching.memory\\7.0.0\\microsoft.extensions.caching.memory.7.0.0.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.configuration\\7.0.0\\microsoft.extensions.configuration.7.0.0.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\7.0.0\\microsoft.extensions.configuration.abstractions.7.0.0.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.configuration.binder\\7.0.4\\microsoft.extensions.configuration.binder.7.0.4.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\7.0.0\\microsoft.extensions.dependencyinjection.7.0.0.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\7.0.0\\microsoft.extensions.dependencyinjection.abstractions.7.0.0.nupkg.sha512",
|
||||
"C:\\Users\\tekh\\.nuget\\packages\\microsoft.extensions.logging\\7.0.0\\microsoft.extensions.logging.7.0.0.nupkg.sha512",
|
||||
|
||||
Reference in New Issue
Block a user