mirror of https://github.com/abpframework/abp.git
committed by
GitHub
21 changed files with 1252 additions and 2 deletions
@ -0,0 +1,24 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.Ldap</AssemblyName> |
||||
|
<PackageId>Volo.Abp.Ldap</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="2.3.8" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Autofac; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAutofacModule) |
||||
|
)] |
||||
|
public class AbpLdapModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
Configure<LdapOptions>(configuration.GetSection("LDAP")); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.Abp.Ldap.Exceptions |
||||
|
{ |
||||
|
public class OrganizationNotExistException : BusinessException |
||||
|
{ |
||||
|
public OrganizationNotExistException(string distinguishedName) |
||||
|
: base("LDAP:000001", $"the organization distinguished named {distinguishedName} does not exist.") |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Ldap.Modeling; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public interface ILdapManager |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// query the specified organizations.
|
||||
|
///
|
||||
|
/// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null
|
||||
|
/// filter: (&(name=*)(objectClass=organizationalUnit)) when name is null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="name"></param>
|
||||
|
/// <returns></returns>
|
||||
|
IList<LdapOrganization> GetOrganizations(string name = null); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// query the specified organization.
|
||||
|
///
|
||||
|
/// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="distinguishedName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
LdapOrganization GetOrganization(string distinguishedName); |
||||
|
|
||||
|
void AddSubOrganization(string organizationName, LdapOrganization parentOrganization); |
||||
|
void AddSubOrganization(string organizationName, string parentDistinguishedName); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// query the specified users.
|
||||
|
///
|
||||
|
/// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null
|
||||
|
/// filter: (&(name=*)(objectCategory=person)(objectClass=user)) when name is null
|
||||
|
///
|
||||
|
/// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null
|
||||
|
/// filter: (&(displayName=*)(objectCategory=person)(objectClass=user)) when displayName is null
|
||||
|
///
|
||||
|
/// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null
|
||||
|
/// filter: (&(cn=*)(objectCategory=person)(objectClass=user)) when commonName is null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="name"></param>
|
||||
|
/// <param name="displayName"></param>
|
||||
|
/// <param name="commonName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
IList<LdapUser> GetUsers(string name = null, string displayName = null, string commonName = null); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// query the specified User.
|
||||
|
///
|
||||
|
/// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="distinguishedName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
LdapUser GetUser(string distinguishedName); |
||||
|
|
||||
|
void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization); |
||||
|
void AddUserToOrganization(string userName, string password, string parentDistinguishedName); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Authenticate
|
||||
|
/// </summary>
|
||||
|
/// <param name="userDomainName">E.g administrator@yourdomain.com.cn </param>
|
||||
|
/// <param name="password"></param>
|
||||
|
/// <returns></returns>
|
||||
|
bool Authenticate(string userDomainName, string password); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public class LdapCredentials |
||||
|
{ |
||||
|
public string DomainUserName { get; set; } |
||||
|
|
||||
|
public string Password { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public static class LdapHelps |
||||
|
{ |
||||
|
public static string BuildCondition(string name, string value) |
||||
|
{ |
||||
|
return string.IsNullOrWhiteSpace(value) ? "" : $"({name}={value})"; |
||||
|
} |
||||
|
|
||||
|
public static string BuildFilter(Dictionary<string,string> conditions) |
||||
|
{ |
||||
|
if (null == conditions ) |
||||
|
{ |
||||
|
conditions = new Dictionary<string, string>(); |
||||
|
} |
||||
|
|
||||
|
if (conditions.Keys.Count == 0) |
||||
|
{ |
||||
|
conditions.Add("objectClass", "*"); // add default condition
|
||||
|
} |
||||
|
|
||||
|
var subFilter = string.Empty; |
||||
|
foreach (var keyValuePair in conditions) |
||||
|
{ |
||||
|
subFilter += BuildCondition(keyValuePair.Key, keyValuePair.Value); |
||||
|
} |
||||
|
|
||||
|
return $"(&{subFilter})"; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,332 @@ |
|||||
|
using System; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Novell.Directory.Ldap; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Ldap.Exceptions; |
||||
|
using Volo.Abp.Ldap.Modeling; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public class LdapManager : ILdapManager, ITransientDependency |
||||
|
{ |
||||
|
private readonly string _searchBase; |
||||
|
private readonly LdapOptions _ldapOptions; |
||||
|
|
||||
|
private readonly string[] _attributes = |
||||
|
{ |
||||
|
"objectCategory", "objectClass", "cn", "name", "distinguishedName", |
||||
|
"ou", |
||||
|
"sAMAccountName", "userPrincipalName", "telephoneNumber", "mail" |
||||
|
}; |
||||
|
|
||||
|
public LdapManager(IOptions<LdapOptions> ldapSettingsOptions) |
||||
|
{ |
||||
|
_ldapOptions = ldapSettingsOptions.Value; |
||||
|
_searchBase = _ldapOptions.SearchBase; |
||||
|
} |
||||
|
|
||||
|
#region Organization
|
||||
|
/// <summary>
|
||||
|
/// query the specified organizations.
|
||||
|
///
|
||||
|
/// filter: (&(name=xxx)(objectClass=organizationalUnit)) when name is not null
|
||||
|
/// filter: (&(objectClass=organizationalUnit)) when name is null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="name"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public IList<LdapOrganization> GetOrganizations(string name = null) |
||||
|
{ |
||||
|
var conditions = new Dictionary<string, string> |
||||
|
{ |
||||
|
{"name", name}, |
||||
|
{"objectClass", "organizationalUnit"}, |
||||
|
}; |
||||
|
return Query<LdapOrganization>(_searchBase, conditions); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// query the specified organization.
|
||||
|
///
|
||||
|
/// filter: (&(distinguishedName=xxx)(objectClass=organizationalUnit)) when organizationName is not null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="distinguishedName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public LdapOrganization GetOrganization(string distinguishedName) |
||||
|
{ |
||||
|
distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); |
||||
|
var conditions = new Dictionary<string, string> |
||||
|
{ |
||||
|
{"distinguishedName", distinguishedName}, |
||||
|
{"objectClass", "organizationalUnit"}, |
||||
|
}; |
||||
|
return QueryOne<LdapOrganization>(_searchBase, conditions); |
||||
|
} |
||||
|
|
||||
|
public void AddSubOrganization(string organizationName, LdapOrganization parentOrganization) |
||||
|
{ |
||||
|
organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); |
||||
|
var dn = $"OU={organizationName},{parentOrganization.DistinguishedName}"; |
||||
|
|
||||
|
var attributeSet = new LdapAttributeSet |
||||
|
{ |
||||
|
new LdapAttribute("objectCategory", $"CN=Organizational-Unit,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), |
||||
|
new LdapAttribute("objectClass", new[] {"top", "organizationalUnit"}), |
||||
|
new LdapAttribute("name", organizationName), |
||||
|
}; |
||||
|
|
||||
|
var newEntry = new LdapEntry(dn, attributeSet); |
||||
|
|
||||
|
using (var ldapConnection = GetConnection()) |
||||
|
{ |
||||
|
ldapConnection.Add(newEntry); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void AddSubOrganization(string organizationName, string parentDistinguishedName) |
||||
|
{ |
||||
|
organizationName = Check.NotNullOrWhiteSpace(organizationName, nameof(organizationName)); |
||||
|
parentDistinguishedName = |
||||
|
Check.NotNullOrWhiteSpace(parentDistinguishedName, nameof(parentDistinguishedName)); |
||||
|
|
||||
|
var parentOrganization = GetOrganization(parentDistinguishedName); |
||||
|
if (null == parentOrganization) |
||||
|
{ |
||||
|
throw new OrganizationNotExistException(parentDistinguishedName); |
||||
|
} |
||||
|
|
||||
|
AddSubOrganization(organizationName, parentOrganization); |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region User
|
||||
|
/// <summary>
|
||||
|
/// query the specified users.
|
||||
|
///
|
||||
|
/// filter: (&(name=xxx)(objectCategory=person)(objectClass=user)) when name is not null
|
||||
|
/// filter: (&(objectCategory=person)(objectClass=user)) when name is null
|
||||
|
///
|
||||
|
/// filter: (&(displayName=xxx)(objectCategory=person)(objectClass=user)) when displayName is not null
|
||||
|
/// filter: (&(objectCategory=person)(objectClass=user)) when displayName is null
|
||||
|
///
|
||||
|
/// filter: (&(cn=xxx)(objectCategory=person)(objectClass=user)) when commonName is not null
|
||||
|
/// filter: (&(objectCategory=person)(objectClass=user)) when commonName is null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="name"></param>
|
||||
|
/// <param name="displayName"></param>
|
||||
|
/// <param name="commonName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public IList<LdapUser> GetUsers(string name = null, string displayName = null, string commonName = null) |
||||
|
{ |
||||
|
var conditions = new Dictionary<string, string> |
||||
|
{ |
||||
|
{"objectCategory", "person"}, |
||||
|
{"objectClass", "user"}, |
||||
|
{"name", name}, |
||||
|
{"displayName", displayName}, |
||||
|
{"cn", commonName}, |
||||
|
}; |
||||
|
return Query<LdapUser>(_searchBase, conditions); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// query the specified User.
|
||||
|
///
|
||||
|
/// filter: (&(distinguishedName=xxx)(objectCategory=person)(objectClass=user)) when distinguishedName is not null
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="distinguishedName"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public LdapUser GetUser(string distinguishedName) |
||||
|
{ |
||||
|
distinguishedName = Check.NotNullOrWhiteSpace(distinguishedName, nameof(distinguishedName)); |
||||
|
var conditions = new Dictionary<string, string> |
||||
|
{ |
||||
|
{"objectCategory", "person"}, |
||||
|
{"objectClass", "user"}, |
||||
|
{"distinguishedName", distinguishedName}, |
||||
|
}; |
||||
|
return QueryOne<LdapUser>(_searchBase, conditions); |
||||
|
} |
||||
|
|
||||
|
public void AddUserToOrganization(string userName, string password, LdapOrganization parentOrganization) |
||||
|
{ |
||||
|
var dn = $"CN={userName},{parentOrganization.DistinguishedName}"; |
||||
|
var mail = $"{userName}@{_ldapOptions.DomainName}"; |
||||
|
sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); |
||||
|
|
||||
|
var attributeSet = new LdapAttributeSet |
||||
|
{ |
||||
|
new LdapAttribute("instanceType", "4"), |
||||
|
new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), |
||||
|
new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), |
||||
|
new LdapAttribute("name", userName), |
||||
|
new LdapAttribute("cn", userName), |
||||
|
new LdapAttribute("sAMAccountName", userName), |
||||
|
new LdapAttribute("userPrincipalName", userName), |
||||
|
new LdapAttribute("sn", userName), |
||||
|
new LdapAttribute("displayName", userName), |
||||
|
new LdapAttribute("unicodePwd", encodedBytes), |
||||
|
new LdapAttribute("userAccountControl", "512"), |
||||
|
new LdapAttribute("mail", mail), |
||||
|
}; |
||||
|
var newEntry = new LdapEntry(dn, attributeSet); |
||||
|
|
||||
|
using (var ldapConnection = GetConnection()) |
||||
|
{ |
||||
|
ldapConnection.Add(newEntry); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void AddUserToOrganization(string userName, string password, string parentDistinguishedName) |
||||
|
{ |
||||
|
var dn = $"CN={userName},{parentDistinguishedName}"; |
||||
|
var mail = $"{userName}@{_ldapOptions.DomainName}"; |
||||
|
sbyte[] encodedBytes = SupportClass.ToSByteArray(Encoding.Unicode.GetBytes($"\"{password}\"")); |
||||
|
|
||||
|
var attributeSet = new LdapAttributeSet |
||||
|
{ |
||||
|
new LdapAttribute("instanceType", "4"), |
||||
|
new LdapAttribute("objectCategory", $"CN=Person,CN=Schema,CN=Configuration,{_ldapOptions.DomainDistinguishedName}"), |
||||
|
new LdapAttribute("objectClass", new[] {"top", "person", "organizationalPerson", "user"}), |
||||
|
new LdapAttribute("name", userName), |
||||
|
new LdapAttribute("cn", userName), |
||||
|
new LdapAttribute("sAMAccountName", userName), |
||||
|
new LdapAttribute("userPrincipalName", userName), |
||||
|
new LdapAttribute("sn", userName), |
||||
|
new LdapAttribute("displayName", userName), |
||||
|
new LdapAttribute("unicodePwd", encodedBytes), |
||||
|
new LdapAttribute("userAccountControl", "512"), |
||||
|
new LdapAttribute("mail", mail), |
||||
|
}; |
||||
|
var newEntry = new LdapEntry(dn, attributeSet); |
||||
|
|
||||
|
using (var ldapConnection = GetConnection()) |
||||
|
{ |
||||
|
ldapConnection.Add(newEntry); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region Authenticate
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Authenticate
|
||||
|
/// </summary>
|
||||
|
/// <param name="userDomainName">E.g administrator@yourdomain.com.cn </param>
|
||||
|
/// <param name="password"></param>
|
||||
|
/// <returns></returns>
|
||||
|
public bool Authenticate(string userDomainName, string password) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
using (GetConnection(userDomainName, password)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
private ILdapConnection GetConnection(string bindUserName = null, string bindUserPassword = null) |
||||
|
{ |
||||
|
// bindUserName/bindUserPassword only be used when authenticate
|
||||
|
bindUserName = bindUserName ?? _ldapOptions.Credentials.DomainUserName; |
||||
|
bindUserPassword = bindUserPassword ?? _ldapOptions.Credentials.Password; |
||||
|
|
||||
|
var ldapConnection = new LdapConnection() { SecureSocketLayer = _ldapOptions.UseSsl }; |
||||
|
if (_ldapOptions.UseSsl) |
||||
|
{ |
||||
|
ldapConnection.UserDefinedServerCertValidationDelegate += (sender, certificate, chain, sslPolicyErrors) => true; |
||||
|
} |
||||
|
ldapConnection.Connect(_ldapOptions.ServerHost, _ldapOptions.ServerPort); |
||||
|
|
||||
|
if (_ldapOptions.UseSsl) |
||||
|
{ |
||||
|
ldapConnection.Bind(LdapConnection.Ldap_V3, bindUserName, bindUserPassword); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
ldapConnection.Bind(bindUserName, bindUserPassword); |
||||
|
} |
||||
|
return ldapConnection; |
||||
|
} |
||||
|
|
||||
|
private IList<T> Query<T>(string searchBase, Dictionary<string, string> conditions) where T : class, ILdapEntry |
||||
|
{ |
||||
|
var filter = LdapHelps.BuildFilter(conditions); |
||||
|
|
||||
|
var result = new List<T>(); |
||||
|
|
||||
|
using (var ldapConnection = GetConnection()) |
||||
|
{ |
||||
|
var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, |
||||
|
_attributes, false, null, null); |
||||
|
|
||||
|
LdapMessage message; |
||||
|
while ((message = search.getResponse()) != null) |
||||
|
{ |
||||
|
if (!(message is LdapSearchResult searchResultMessage)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
var entry = searchResultMessage.Entry; |
||||
|
if (typeof(T) == typeof(LdapOrganization)) |
||||
|
{ |
||||
|
result.Add(new LdapOrganization(entry.getAttributeSet()) as T); |
||||
|
} |
||||
|
|
||||
|
if (typeof(T) == typeof(LdapUser)) |
||||
|
{ |
||||
|
result.Add(new LdapUser(entry.getAttributeSet()) as T); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private T QueryOne<T>(string searchBase, Dictionary<string, string> conditions) where T : class, ILdapEntry |
||||
|
{ |
||||
|
var filter = LdapHelps.BuildFilter(conditions); |
||||
|
|
||||
|
using (var ldapConnection = GetConnection()) |
||||
|
{ |
||||
|
var search = ldapConnection.Search(searchBase, LdapConnection.SCOPE_SUB, filter, |
||||
|
_attributes, false, null, null); |
||||
|
|
||||
|
LdapMessage message; |
||||
|
while ((message = search.getResponse()) != null) |
||||
|
{ |
||||
|
if (!(message is LdapSearchResult searchResultMessage)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
var entry = searchResultMessage.Entry; |
||||
|
if (typeof(T) == typeof(LdapOrganization)) |
||||
|
{ |
||||
|
return new LdapOrganization(entry.getAttributeSet()) as T; |
||||
|
} |
||||
|
|
||||
|
if (typeof(T) == typeof(LdapUser)) |
||||
|
{ |
||||
|
return new LdapUser(entry.getAttributeSet()) as T; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public class LdapOptions |
||||
|
{ |
||||
|
public string ServerHost { get; set; } |
||||
|
|
||||
|
public int ServerPort { get; set; } |
||||
|
|
||||
|
public bool UseSsl { get; set; } |
||||
|
|
||||
|
public string SearchBase { get; set; } |
||||
|
|
||||
|
public string DomainName { get; set; } |
||||
|
|
||||
|
public string DomainDistinguishedName { get; set; } |
||||
|
|
||||
|
public LdapCredentials Credentials { get; set; } |
||||
|
|
||||
|
public LdapOptions() |
||||
|
{ |
||||
|
Credentials = new LdapCredentials(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public interface ILdapEntry |
||||
|
{ |
||||
|
string ObjectCategory { get; set; } |
||||
|
string[] ObjectClass { get; set; } |
||||
|
string Name { get; set; } |
||||
|
string DistinguishedName { get; set; } |
||||
|
string CommonName { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public interface ILdapOrganization : ILdapEntry |
||||
|
{ |
||||
|
string OrganizationUnit { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public interface ILdapUser : ILdapEntry |
||||
|
{ |
||||
|
string SamAccountName { get; set; } |
||||
|
string UserPrincipalName { get; set; } |
||||
|
string DisplayName { get; set; } |
||||
|
string Email { get; set; } |
||||
|
string Phone { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using Novell.Directory.Ldap; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public abstract class LdapEntryBase : ILdapEntry |
||||
|
{ |
||||
|
public string ObjectCategory { get; set; } |
||||
|
public string[] ObjectClass { get; set; } |
||||
|
public string Name { get; set; } |
||||
|
public string CommonName { get; set; } |
||||
|
public string DistinguishedName { get; set; } |
||||
|
|
||||
|
protected LdapEntryBase() { } |
||||
|
|
||||
|
protected LdapEntryBase(LdapAttributeSet attributeSet) |
||||
|
{ |
||||
|
ObjectCategory = attributeSet.getAttribute("objectCategory")?.StringValue; |
||||
|
ObjectClass = attributeSet.getAttribute("objectClass")?.StringValueArray; |
||||
|
Name = attributeSet.getAttribute("name")?.StringValue; |
||||
|
CommonName = attributeSet.getAttribute("cn")?.StringValue; |
||||
|
DistinguishedName = attributeSet.getAttribute("distinguishedName")?.StringValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Novell.Directory.Ldap; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public class LdapOrganization : LdapEntryBase, ILdapOrganization |
||||
|
{ |
||||
|
public string OrganizationUnit { get; set; } |
||||
|
|
||||
|
public LdapOrganization() { } |
||||
|
|
||||
|
public LdapOrganization(LdapAttributeSet attributeSet) |
||||
|
: base(attributeSet) |
||||
|
{ |
||||
|
OrganizationUnit = attributeSet.getAttribute("ou")?.StringValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using Novell.Directory.Ldap; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap.Modeling |
||||
|
{ |
||||
|
public class LdapUser : LdapEntryBase, ILdapUser |
||||
|
{ |
||||
|
public string SamAccountName { get; set; } |
||||
|
public string UserPrincipalName { get; set; } |
||||
|
public string DisplayName { get; set; } |
||||
|
public string Email { get; set; } |
||||
|
public string Phone { get; set; } |
||||
|
|
||||
|
public LdapUser() { } |
||||
|
|
||||
|
public LdapUser( LdapAttributeSet attributeSet) |
||||
|
: base(attributeSet) |
||||
|
{ |
||||
|
SamAccountName = attributeSet.getAttribute("sAMAccountName")?.StringValue; |
||||
|
UserPrincipalName = attributeSet.getAttribute("userPrincipalName")?.StringValue; |
||||
|
DisplayName = attributeSet.getAttribute("displayName")?.StringValue; |
||||
|
Email = attributeSet.getAttribute("mail")?.StringValue; |
||||
|
Phone = attributeSet.getAttribute("telephoneNumber")?.StringValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,173 @@ |
|||||
|
# Volo.Abp.Ldap |
||||
|
|
||||
|
# Only Authenticate(not read/write AD) |
||||
|
|
||||
|
## Configure |
||||
|
|
||||
|
add section in `appsettings.json` |
||||
|
|
||||
|
### use SSL |
||||
|
|
||||
|
```json |
||||
|
"LDAP": { |
||||
|
"ServerHost": "192.168.101.54", |
||||
|
"ServerPort": 636, |
||||
|
"UseSSL": true |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### not use SSL |
||||
|
|
||||
|
```json |
||||
|
"LDAP": { |
||||
|
"ServerHost": "192.168.101.54", |
||||
|
"ServerPort": 389, |
||||
|
"UseSSL": false |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## Authenticate |
||||
|
|
||||
|
Injecting `ILdapManager` into a class. For example: |
||||
|
|
||||
|
```csharp |
||||
|
public class TaxAppService : ApplicationService |
||||
|
{ |
||||
|
private readonly ILdapManager _ldapManager; |
||||
|
|
||||
|
public TaxAppService(ILdapManager ldapManager) |
||||
|
{ |
||||
|
_ldapManager = ldapManager; |
||||
|
} |
||||
|
|
||||
|
public void Authenticate(string userName, string password) |
||||
|
{ |
||||
|
var result = _ldapManager.Authenticate(userName, password); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- `userName` must be full domain name. E.g abc@abc.com |
||||
|
|
||||
|
# Read/Write AD |
||||
|
|
||||
|
## Configure |
||||
|
|
||||
|
### use SSL |
||||
|
|
||||
|
```json |
||||
|
"LDAP": { |
||||
|
"ServerHost": "192.168.101.54", |
||||
|
"ServerPort": 636, |
||||
|
"UseSSL": true, |
||||
|
"Credentials": { |
||||
|
"DomainUserName": "administrator@yourdomain.com.cn", |
||||
|
"Password": "yH.20190528" |
||||
|
}, |
||||
|
"SearchBase": "DC=yourdomain,DC=com,DC=cn", |
||||
|
"DomainName": "yourdomain.com.cn", |
||||
|
"DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### not use SSL |
||||
|
|
||||
|
```json |
||||
|
"LDAP": { |
||||
|
"ServerHost": "192.168.101.54", |
||||
|
"ServerPort": 389, |
||||
|
"UseSSL": false, |
||||
|
"Credentials": { |
||||
|
"DomainUserName": "administrator@yourdomain.com.cn", |
||||
|
"Password": "yH.20190528" |
||||
|
}, |
||||
|
"SearchBase": "DC=yourdomain,DC=com,DC=cn", |
||||
|
"DomainName": "yourdomain.com.cn", |
||||
|
"DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- `Credentials:DomainUserName` a administrator of AD. |
||||
|
|
||||
|
- `Credentials:Password` the password for the administrator. |
||||
|
- `SearchBase`: where search from AD. |
||||
|
- `DomainName`: name of you domain. no need `www`. |
||||
|
- `DomainDistinguishedName`: distinguished name of root domain. |
||||
|
|
||||
|
## Query Organizations |
||||
|
|
||||
|
```cs |
||||
|
// query all organizations |
||||
|
// filter: (&(objectClass=organizationalUnit)) |
||||
|
_ldapManager.GetOrganizations(); |
||||
|
|
||||
|
// query organizations by name |
||||
|
// filter: (&(name=abc)(objectClass=organizationalUnit)) |
||||
|
_ldapManager.GetOrganizations("abc"); |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
## Query Organization |
||||
|
|
||||
|
```csharp |
||||
|
// query organization by distinguished name |
||||
|
// filter: (&(distinguishedName=abc)(objectClass=organizationalUnit)) |
||||
|
_ldapManager.GetOrganization("abc"); |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
## Add Organization |
||||
|
|
||||
|
```csharp |
||||
|
// use LdapOrganization |
||||
|
_ldapManager.AddSubOrganization("nameA", parentOrganization); |
||||
|
|
||||
|
// or use OrganizationDistinguishedName |
||||
|
_ldapManager.AddSubOrganization("nameA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); |
||||
|
``` |
||||
|
|
||||
|
## Query Users |
||||
|
|
||||
|
```cs |
||||
|
// query all users |
||||
|
// filter: (&(objectCategory=person)(objectClass=user)) |
||||
|
_ldapManager.GetUsers(); |
||||
|
|
||||
|
// query organizations by name |
||||
|
// filter: (&(name=abc)(objectCategory=person)(objectClass=user)) |
||||
|
_ldapManager.GetUsers(name : "abc"); |
||||
|
|
||||
|
// query organizations by displayName |
||||
|
// filter: (&(displayName=abc)(objectCategory=person)(objectClass=user)) |
||||
|
_ldapManager.GetUsers(displayName : "abc"); |
||||
|
|
||||
|
// query organization by commonName |
||||
|
// filter: (&(cn=abc)(objectCategory=person)(objectClass=user)) |
||||
|
_ldapManager.GetUsers(commonName : "abc"); |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
## Query User |
||||
|
|
||||
|
```csharp |
||||
|
// query a user by distinguished name |
||||
|
// filter: (&(distinguishedName=abc)(objectCategory=person)(objectClass=user)) |
||||
|
_ldapManager.GetUser("abc"); |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
## Add User |
||||
|
|
||||
|
```csharp |
||||
|
// use LdapOrganization |
||||
|
_ldapManager.AddUserToOrganization("nameA", "passwordA", parentOrganization); |
||||
|
|
||||
|
// or use OrganizationDistinguishedName |
||||
|
_ldapManager.AddUserToOrganization("nameA", "passwordA", "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"); |
||||
|
``` |
||||
|
|
||||
|
# More see [unit test](../../test/Volo.Abp.Ldap.Tests) |
||||
|
|
||||
|
|
||||
|
|
||||
|
# |
||||
@ -0,0 +1,18 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netcoreapp2.2</TargetFramework> |
||||
|
<LangVersion>latest</LangVersion> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Volo.Abp.Ldap\Volo.Abp.Ldap.csproj" /> |
||||
|
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,70 @@ |
|||||
|
using System; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
|
||||
|
public class Authenticate_Tests : AbpIntegratedTest<Authenticate_Tests.TestModule> |
||||
|
{ |
||||
|
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
} |
||||
|
|
||||
|
private readonly ILdapManager _ldapManager; |
||||
|
private readonly LdapTestData _testData; |
||||
|
|
||||
|
public Authenticate_Tests() |
||||
|
{ |
||||
|
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
|
_testData = GetRequiredService<LdapTestData>(); |
||||
|
_ldapManager = GetRequiredService<ILdapManager>(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void Authenticate() |
||||
|
{ |
||||
|
var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); |
||||
|
|
||||
|
result.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void Authenticate_With_Wrong_Password() |
||||
|
{ |
||||
|
var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); |
||||
|
|
||||
|
result.ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[DependsOn(typeof(AbpLdapModule))] |
||||
|
public class TestModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
// not use ssl
|
||||
|
// "LDAP": {
|
||||
|
// "ServerHost": "192.168.101.54",
|
||||
|
// "ServerPort": 389,
|
||||
|
// "UseSSL": false
|
||||
|
// }
|
||||
|
|
||||
|
// use ssl
|
||||
|
// "LDAP": {
|
||||
|
// "ServerHost": "192.168.101.54",
|
||||
|
// "ServerPort": 636,
|
||||
|
// "UseSSL": true
|
||||
|
// }
|
||||
|
Configure<LdapOptions>(settings => |
||||
|
{ |
||||
|
settings.ServerHost = "192.168.101.54"; |
||||
|
settings.ServerPort = 636; |
||||
|
settings.UseSsl = true; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using Shouldly; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public class LdapHelps_Tests |
||||
|
{ |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildCondition_With_Value() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildCondition("objectClass", "testNameA"); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBe("(objectClass=testNameA)"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildCondition_With_Null_Value() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildCondition("objectClass", null); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildCondition_With_Empty_Value() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildCondition("objectClass", ""); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildCondition_With_WhiteSpace_Value() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildCondition("objectClass", " "); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildFilter_With_Null_Condition() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildFilter(null); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBe("(&(objectClass=*))"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildFilter_With_Empty_Condition() |
||||
|
{ |
||||
|
// act
|
||||
|
var res = LdapHelps.BuildFilter(new Dictionary<string, string>()); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBe("(&(objectClass=*))"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void BuildFilter_With_Condition() |
||||
|
{ |
||||
|
// act
|
||||
|
var conditions = new Dictionary<string, string> |
||||
|
{ |
||||
|
{"objectClass", "testClassA"}, {"objectCategory", "testCategoryA"}, {"name", null} |
||||
|
}; |
||||
|
var res = LdapHelps.BuildFilter(conditions); |
||||
|
|
||||
|
// assert
|
||||
|
res.ShouldBe("(&(objectClass=testClassA)(objectCategory=testCategoryA))"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,245 @@ |
|||||
|
using System; |
||||
|
using Shouldly; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
|
||||
|
public class LdapManager_Tests : AbpIntegratedTest<LdapManager_Tests.TestModule> |
||||
|
{ |
||||
|
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
||||
|
{ |
||||
|
options.UseAutofac(); |
||||
|
} |
||||
|
|
||||
|
private readonly ILdapManager _ldapManager; |
||||
|
private readonly LdapTestData _testData; |
||||
|
|
||||
|
public LdapManager_Tests() |
||||
|
{ |
||||
|
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
|
_testData = GetRequiredService<LdapTestData>(); |
||||
|
_ldapManager = GetRequiredService<ILdapManager>(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetOrganizations_With_Empty_Condition() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganizations(); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == _testData.DomainControllersName); |
||||
|
result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetOrganizations_With_Name() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganizations(_testData.DomainControllersName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldHaveSingleItem(); |
||||
|
result.ShouldContain(e => e.Name == _testData.DomainControllersName); |
||||
|
result.ShouldContain(e => e.DistinguishedName == _testData.DomainControllersDistinguishedName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetOrganizations_With_Non_Existent_Name() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganizations("NonExistentNameA"); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetOrganization() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.Name.ShouldBe(_testData.DomainControllersName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetOrganization_With_Non_Existent_DistinguishedName() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganization("NonExistentNameA"); |
||||
|
|
||||
|
result.ShouldBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_Empty_Condition() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == _testData.AdministratorName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_Name() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(name: _testData.AdministratorName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == _testData.AdministratorName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_Non_Existent_Name() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(name: "NonExistentNameA"); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_CommonName() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(commonName: _testData.AdministratorName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == _testData.AdministratorName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_Non_Existent_CommonName() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(commonName: "NonExistentNameA"); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUsers_With_DisplayName() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUsers(displayName: _testData.AdministratorName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
// the administrator in AD. not have display name by default.
|
||||
|
result.ShouldBeEmpty(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUser() |
||||
|
{ |
||||
|
var result = _ldapManager.GetUser(_testData.AdministratorDistinguishedName); |
||||
|
|
||||
|
result.ShouldNotBeNull(); |
||||
|
result.Name.ShouldBe(_testData.AdministratorName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void GetUser_With_Non_Existent_DistinguishedName() |
||||
|
{ |
||||
|
var result = _ldapManager.GetOrganization("NonExistentNameA"); |
||||
|
|
||||
|
result.ShouldBeNull(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void Authenticate() |
||||
|
{ |
||||
|
var result = _ldapManager.Authenticate(_testData.AdministratorDomainName, _testData.AdministratorPassword); |
||||
|
|
||||
|
result.ShouldBeTrue(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void Authenticate_With_Wrong_Password() |
||||
|
{ |
||||
|
var result = _ldapManager.Authenticate("NonExistentNameA", "PasswordA"); |
||||
|
|
||||
|
result.ShouldBeFalse(); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void AddSubOrganization() |
||||
|
{ |
||||
|
var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); |
||||
|
var randomName = $"Test_{DateTime.Now.Ticks}"; |
||||
|
|
||||
|
_ldapManager.AddSubOrganization(randomName, parentOrganization); |
||||
|
|
||||
|
var result = _ldapManager.GetOrganizations(randomName); |
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == randomName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void AddSubOrganization_With_DistinguishedName() |
||||
|
{ |
||||
|
var randomName = $"Test_{DateTime.Now.Ticks}"; |
||||
|
|
||||
|
_ldapManager.AddSubOrganization(randomName, _testData.DomainControllersDistinguishedName); |
||||
|
|
||||
|
var result = _ldapManager.GetOrganizations(randomName); |
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e => e.Name == randomName); |
||||
|
} |
||||
|
|
||||
|
[Fact(Skip = "need environment AD ")] |
||||
|
public void AddOrganizationUser() |
||||
|
{ |
||||
|
var parentOrganization = _ldapManager.GetOrganization(_testData.DomainControllersDistinguishedName); |
||||
|
var randomName = $"Test_{DateTime.Now:yyMMddHHmmss}"; |
||||
|
_ldapManager.AddUserToOrganization(randomName, _testData.AdministratorPassword, parentOrganization); |
||||
|
|
||||
|
var result = _ldapManager.GetUsers(randomName); |
||||
|
result.ShouldNotBeNull(); |
||||
|
result.ShouldContain(e=>e.Name == randomName); |
||||
|
} |
||||
|
|
||||
|
[DependsOn(typeof(AbpLdapModule))] |
||||
|
public class TestModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
// not use ssl
|
||||
|
// "LDAP": {
|
||||
|
// "ServerHost": "192.168.101.54",
|
||||
|
// "ServerPort": 389,
|
||||
|
// "UseSSL": false,
|
||||
|
// "Credentials": {
|
||||
|
// "DomainUserName": "administrator@yourdomain.com.cn",
|
||||
|
// "Password": "yH.20190528"
|
||||
|
// },
|
||||
|
// "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn",
|
||||
|
// "DomainName": "yourdomain.com.cn",
|
||||
|
// "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn"
|
||||
|
// }
|
||||
|
|
||||
|
// use ssl
|
||||
|
// "LDAP": {
|
||||
|
// "ServerHost": "192.168.101.54",
|
||||
|
// "ServerPort": 636,
|
||||
|
// "UseSSL": true,
|
||||
|
// "Credentials": {
|
||||
|
// "DomainUserName": "administrator@yourdomain.com.cn",
|
||||
|
// "Password": "yH.20190528"
|
||||
|
// },
|
||||
|
// "SearchBase": "CN=Users,DC=yourdomain,DC=com,DC=cn",
|
||||
|
// "DomainName": "yourdomain.com.cn",
|
||||
|
// "DomainDistinguishedName": "DC=yourdomain,DC=com,DC=cn"
|
||||
|
// }
|
||||
|
Configure<LdapOptions>(settings => |
||||
|
{ |
||||
|
settings.ServerHost = "192.168.101.54"; |
||||
|
settings.ServerPort = 636; |
||||
|
settings.UseSsl = true; |
||||
|
settings.Credentials.DomainUserName = "administrator@yourdomain.com.cn"; |
||||
|
settings.Credentials.Password = "yH.20190528"; |
||||
|
settings.SearchBase = "DC=yourdomain,DC=com,DC=cn"; |
||||
|
settings.DomainName = "yourdomain.com.cn"; |
||||
|
settings.DomainDistinguishedName = "DC=yourdomain,DC=com,DC=cn"; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Ldap |
||||
|
{ |
||||
|
public class LdapTestData : ISingletonDependency |
||||
|
{ |
||||
|
public string AdministratorName { get; } = "Administrator"; |
||||
|
public string AdministratorPassword { get; } = "yH.20190528"; |
||||
|
public string AdministratorDistinguishedName { get; } = "CN=Administrator,CN=Users,DC=yourdomain,DC=com,DC=cn"; |
||||
|
public string AdministratorDomainName { get; } = "Administrator@yourdomain.com.cn"; |
||||
|
|
||||
|
public string DomainControllersName = "Domain Controllers"; |
||||
|
public string DomainControllersDistinguishedName = "OU=Domain Controllers,DC=yourdomain,DC=com,DC=cn"; |
||||
|
|
||||
|
public string RootDistinguishedName { get; } = "DC=yourdomain,DC=com,DC=cn"; |
||||
|
|
||||
|
public string Organization001Name { get; } = "Test_A"; |
||||
|
|
||||
|
public string Test001Name { get; } = "test001"; |
||||
|
public string Test001Password { get; } = "yH.20190528"; |
||||
|
public string Test001Email { get; } = "test001@yourdomain.com.cn"; |
||||
|
|
||||
|
public string Test002Name { get; } = "test002"; |
||||
|
public string Test002Password { get; } = "yH.20190528"; |
||||
|
public string Test002WrongPassword { get; } = "yH.20190529"; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue