Je dois modifier le nom d'utilisateur (Windows) existant de mon application ASP.NET MVC + Knockout avec authentification Active Directory . Il est composé de contrôleurs MVC et de contrôleurs WebAPI. Les deux doivent être authentifiés.
Je pensais que je le ferais en passant à forms authentication
et en créant une page de connexion. Lorsque les utilisateurs cliquent sur le bouton de connexion, interrogez Active Directory avec le System.DirectoryServices.DirectoryEntry
. Les autres processus, tels que la modification du mot de passe, l'enregistrement, obtiennent également une page HTML personnalisée. et faire leurs actions via le System.DirectoryServices.DirectoryEntry
sur notre Active Directory.
(c’est-à-dire que je ne pouvais trouver aucun autre moyen de le faire, et j’en ai trouvé qui le ferait de la sorte, et cela ressemble au précédent forms authentication
s que j’ai vu. Dans ce cas, l’utilisateur/les mots de passe ne seraient pas dans une table de base de données, mais dans Active Directory. Même idée, permuter la table de base de données par Active Directory).
Pour voir comment cela se passerait sur un nouveau projet, j'ai créé un nouveau projet ASP.NET MVC et choisi "Comptes professionnels" (qui signifie "pour les applications qui authentifient les utilisateurs avec Active Directory), puis" sur site " Cependant, je dois alors fournir ces éléments:
Je ne sais pas quoi faire avec ça. La seule chose que j'ai est une URL Active Directory comme ldap://etc.
.
Est-ce une autre/nouvelle/meilleure façon de se connecter à Active Directory? Ou le seul qui soit correct (l'authentification par formulaires est-elle erronée?) Ou le mauvais?
Je suis confus.
J'ai utilisé l'approche suivante pour implémenter l'authentification Active Directory dans ASP.NET MVC 5
et cela fonctionne comme un charme:
Étape 1:Modifiez les méthodes de connexion dans la AccountController
comme indiqué ci-dessous (ajoutez également les références nécessaires):
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
try
{
if (!ModelState.IsValid)
{
return View(model);
}
// Check if the User exists in LDAP
if (Membership.GetUser(model.UserName) == null)
{
ModelState.AddModelError("", "Wrong username or password");
return this.View(model);
}
ApplicationGroupManager groupManager = new ApplicationGroupManager();
// Validate the user using LDAP
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
// FormsAuthentication.SetAuthCookie(model.UserName, false);
// Check if the User exists in the ASP.NET Identity table (AspNetUsers)
string userName = model.UserName.ToString().ToLower(new CultureInfo("en-US", false)); // When UserName is entered in uppercase containing "I", the user cannot be found in LDAP
//ApplicationUser user = UserManager.FindByName(userName);
ApplicationUser user = await UserManager.FindByNameAsync(userName); //Asynchronous method
if (user == null) // If the User DOES NOT exists in the ASP.NET Identity table (AspNetUsers)
{
// Create a new user using the User data retrieved from LDAP
// Create an array of properties that we would like and add them to the search object
string[] requiredProperties = new string[] { "samaccountname", "givenname", "sn", "mail", "physicalDeliveryOfficeName", "title" };
var userInfo = CreateDirectoryEntry(model.UserName, requiredProperties);
user = new ApplicationUser();
// For more information about "User Attributes - Inside Active Directory" : http://www.kouti.com/tables/userattributes.htm
user.UserName = userInfo.GetDirectoryEntry().Properties["samaccountname"].Value.ToString();
user.Name = userInfo.GetDirectoryEntry().Properties["givenname"].Value.ToString();
user.Surname = userInfo.GetDirectoryEntry().Properties["sn"].Value.ToString();
user.Email = userInfo.GetDirectoryEntry().Properties["mail"].Value.ToString();
user.EmailConfirmed = true;
//user.PasswordHash = null;
//user.Department = GetDepartmentId(userInfo.GetDirectoryEntry().Properties["physicalDeliveryOfficeName"].Value.ToString());
//await Register(user);
var result = await UserManager.CreateAsync(user); //Asynchronous method
//If the User has succesfully been created
//if (result.Succeeded)
//{
// //var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// //await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
// //ViewBag.Link = callbackUrl;
// //return View("DisplayEmail");
//}
// Define user group (and roles)
var defaultGroup = "751b30d7-80be-4b3e-bfdb-3ff8c13be05e"; // Id of the ApplicationGroup for the Default roles
//groupManager.SetUserGroups(newUser.Id, new string[] { defaultGroup });
await groupManager.SetUserGroupsAsync(user.Id, new string[] { defaultGroup }); //Asynchronous method
//groupManager.SetGroupRoles(newGroup.Id, new string[] { role.Name });
}
// !!! THERE IS NO NEED TO ASSIGN ROLES AS IT IS ASSIGNED AUTOMATICALLY IN ASP.NET Identity 2.0
//else // If the User exists in the ASP.NET Identity table (AspNetUsers)
//{
// //##################### Some useful ASP.NET Identity 2.0 methods (for Info) #####################
// //ApplicationGroupManager gm = new ApplicationGroupManager();
// //string roleName = RoleManager.FindById("").Name; // Returns Role Name by using Role Id parameter
// //var userGroupRoles = gm.GetUserGroupRoles(""); // Returns Group Id and Role Id by using User Id parameter
// //var groupRoles = gm.GetGroupRoles(""); // Returns Group Roles by using Group Id parameter
// //string[] groupRoleNames = groupRoles.Select(p => p.Name).ToArray(); // Assing Group Role Names to a string array
// //###############################################################################################
// // Assign Default ApplicationGroupRoles to the User
// // As the default roles are already defined to the User after the first login to the system, there is no need to check if the role is NULL (otherwise it must be checked!!!)
// //var groupRoles = groupManager.GetGroupRoles("751b30d7-80be-4b3e-bfdb-3ff8c13be05e"); // Returns Group Roles by using Group Id parameter
// var groupRoles = await groupManager.GetGroupRolesAsync("751b30d7-80be-4b3e-bfdb-3ff8c13be05e"); // Returns Group Roles by using Group Id parameter (Asynchronous method)
// foreach (var role in groupRoles)
// {
// //Assign ApplicationGroupRoles to the User
// string roleName = RoleManager.FindById(role.Id).Name;
// UserManager.AddToRole(user.Id, roleName);
// }
//}
//Sign in the user
await SignInAsync(user, model.RememberMe);
if (this.Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return this.Redirect(returnUrl);
//return RedirectToLocal(returnUrl);
}
return this.RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Wrong username or password");
return this.View(model);
}
}
catch (Exception ex)
{
TempData["ErrorMessage"] = ex.Message.ToString();
return View("Error", TempData["ErrorMessage"]);
}
}
/* Since ASP.NET Identity and OWIN Cookie Authentication are claims-based system, the framework requires the app to generate a ClaimsIdentity for the user.
ClaimsIdentity has information about all the claims for the user, such as what roles the user belongs to. You can also add more claims for the user at this stage.
The highlighted code below in the SignInAsync method signs in the user by using the AuthenticationManager from OWIN and calling SignIn and passing in the ClaimsIdentity. */
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
static SearchResult CreateDirectoryEntry(string sAMAccountName, string[] requiredProperties)
{
DirectoryEntry ldapConnection = null;
try
{
// Create LDAP connection object
//ldapConnection = new DirectoryEntry("alpha.company.com");
ldapConnection = new DirectoryEntry("LDAP://OU=Company_Infrastructure, DC=company, DC=mydomain", "******", "******");
//ldapConnection.Path = connectionPath;
ldapConnection.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher search = new DirectorySearcher(ldapConnection);
search.Filter = String.Format("(sAMAccountName={0})", sAMAccountName);
foreach (String property in requiredProperties)
search.PropertiesToLoad.Add(property);
SearchResult result = search.FindOne();
//SearchResultCollection searchResultCollection = search.FindAll();
if (result != null)
{
//foreach (String property in requiredProperties)
// foreach (Object myCollection in result.Properties[property])
// Console.WriteLine(String.Format("{0,-20} : {1}",
// property, myCollection.ToString()));
// return searchResultCollection;
return result;
}
else
{
return null;
//Console.WriteLine("User not found!");
}
//return ldapConnection;
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return null;
}
Remarque:Pour forcer la déconnexion dans l'authentification LDAP
, ajoutez une ligne FormsAuthentication.SignOut()
à la méthode LogOff()
comme indiqué ci-dessous:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
FormsAuthentication.SignOut(); //In order to force logout in LDAP authentication
return RedirectToAction("Login", "Account");
}
Étape 2:Mettez à jour votre LoginViewModel
(ou le nom de votre classe de modèle de compte) pour ne contenir que cette classe LoginModel
:
public class LoginViewModel
{
[Required]
public string UserName { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool RememberMe { get; set; }
}
D'autre part, ajoutez les propriétés personnalisées, à savoir Nom, Nom, Nom d'utilisateur, Département, etc. au modèle nécessaire, à savoir ApplicationUser
, RegisterViewModel
.
Étape 3:Enfin, mettez à jour votre fichier Web.config
pour inclure ces éléments:
<connectionStrings>
<!-- for LDAP -->
<add name="ADConnectionString" connectionString="LDAP://**.**.***:000/DC=abc,DC=xyz" />
</connectionStrings>
<system.web>
<!-- For LDAP -->
<httpCookies httpOnlyCookies="true" />
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Account/Login" timeout="30" slidingExpiration="true" protection="All" />
</authentication>
<membership defaultProvider="ADMembershipProvider">
<providers>
<clear />
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" connectionUsername="******" connectionPassword="******" />
</providers>
</membership>
...
</system.web>
J'espère que cela t'aides...
J'ai utilisé Active Directory Authetication
au travail . J'ai créé l'application MVC
avec Windows Authetication
et cela a été fait. L'application affiche automatiquement AD
login avec le domaine. Choisissez l'appartenance: [Authorize(Roles=@"DomainName\GroupName")]
Vous pouvez voir le domaine et les groupes dans cmd: Nom d'utilisateur Net /domainVous ne devez pas utiliser LDAP
.
Avec LDAP
voir: voir ici
j'ai un système mixte en cours d'exécution. Utilisateurs d'une base de données (utilisateurs externes) mélangés à des utilisateurs AD (utilisateurs internes) pouvant se connecter à notre système. Pour communiquer avec AD, j'utilise un package de nuget appelé LinqToLdap ( https://github.com/madhatter22/LinqToLdap ). cela utilise le protocole LDAP afin qu'il puisse également être utilisé pour l'authentification auprès des serveurs Unix Ldap.
c'est la méthode d'authentification
public bool AuthenticateUser(string userName, string password)
{
InitConfig();
using (var context = new DirectoryContext(_config))
{
var user = context.Query<LdapUserInfo>().FirstOrDefault(x => x.UserPrincipalName.Equals(userName));
var dn = user?.DistinguishedName;
if (string.IsNullOrWhiteSpace(dn))
return false;
using (var ldap = new LdapConnection(new LdapDirectoryIdentifier(_myConfig.Server)))
{
ldap.SessionOptions.ProtocolVersion = 3;
ldap.AuthType = AuthType.Basic;
ldap.Credential = _credentials;
ldap.Bind();
try
{
ldap.AuthType = AuthType.Basic;
ldap.Bind(new NetworkCredential(dn, password));
return true;
}
catch (DirectoryOperationException)
{ }
catch (LdapException)
{ }
}
return false;
}
}
private void InitConfig()
{
if (_config != null)
return;
_config = new LdapConfiguration();
_credentials = new NetworkCredential(_myConfig.Username, _myConfig.Password, _myConfig.Domain);
_config.AddMapping(new AutoClassMap<LdapGroupInfo>(), _myConfig.NamingContext, new[] { "*" });
_config.AddMapping(new AutoClassMap<LdapUserInfo>(), _myConfig.NamingContext, new[] { "*" });
_config.ConfigureFactory(_myConfig.Server).AuthenticateAs(_credentials).AuthenticateBy(AuthType.Basic);
}