Question

J'ai un scénario dans lequel j'obliger les utilisateurs à être capables d'authentifier une application Web ASP.NET MVC en utilisant l'authentification Windows ou l'authentification par formulaire. Si l'utilisateur est sur le réseau interne, ils utilisent l'authentification Windows et si elles se connectent à l'extérieur, ils utiliseront l'authentification par formulaire. Je l'ai vu pas mal de gens poser la question comment puis-je configurer une application Web ASP.NET MVC pour cela, mais je ne l'ai pas trouvé une explication complète.

S'il vous plaît quelqu'un peut-il fournir une explication détaillée, avec des exemples de code, sur la façon dont cela serait fait?

Merci.

Alan T

Était-ce utile?

La solution

Ceci est appelé mode d'authentification mixte . Fondamentalement, vous ne pouvez pas y parvenir dans un à application, car dans IIS une fois que vous configurez l'authentification Windows pour un répertoire virtuel, il ne sera plus accepter les utilisateurs de différents domaines. Donc, fondamentalement, vous devez avoir deux applications, le premier avec l'authentification Windows et la seconde (l'application principale) en utilisant l'authentification par formulaire. La première application consistera en une seule adresse qui simplement rediriger vers l'application principale en émettant un ticket d'authentification pour l'utilisateur de domaine.

Autres conseils

Cela peut être fait. Inverser la configuration, définissez l'application / root pour utiliser Anonymous et formulaires d'authentification ... De cette façon, vous pouvez configurer l'authentification mixte dans la même application Web, mais il est délicat. Alors d'abord, vous devez configurer l'application pour l'authentification par formulaire avec loginUrl = « ~ / WinLogin / WinLogin2.aspx ». Dans MVC, le routage remplace les règles d'authentification définies par IIS, si besoin d'utiliser une page ASPX, comme IIS peut définir l'authentification sur le fichier. Activer l'authentification anonyme et formulaires sur l'application Web racine. Activer l'authentification Windows et désactiver l'authentification anonyme dans le répertoire racine / WinLogin. Ajouter 401 et 401.2 personnalisés pages d'erreur pour rediriger vers le compte / URL Signin.

Cela permettra un navigateur capable de pass-through à utiliser l'authentification Windows intégrée à signin automatique. Alors que certains appareils seront invité à entrer les informations d'identification se (comme l'iPhone) et d'autres appareils tels que BlackBerry redirigés vers la page de connexion.

Cela crée également un cookie en ajoutant explicitement les rôles des utilisateurs et crée un principe générique afin que l'autorisation basée sur les rôles peuvent être utilisés.

dans WinLogin2.aspx (dans le répertoire WinLogin sous application web « root » dans IIS et configuré pour utiliser l'authentification Windows, Anonymous désactivé, et les formes activées (comme ne peut pas désactiver ... note IIS se plaindra lorsque vous activez l'authentification windows, ignorer):

var logonUser = Request.ServerVariables["LOGON_USER"];
        if (!String.IsNullOrWhiteSpace(logonUser))
        {
            if (logonUser.Split('\\').Length > 1)
            {
                var domain = logonUser.Split('\\')[0];
                var username = logonUser.Split('\\')[1];

                var timeout = 30;

                var encTicket = CreateTicketWithSecurityGroups(false, username, domain, timeout);

                var authCookie = new HttpCookie(".MVCAUTH", encTicket) { HttpOnly = true };
                Response.Cookies.Add(authCookie);


            }
            //else
            //{
            // this is a redirect due to returnUrl being WinLogin page, in which logonUser will no longer have domain attached
            //  ignore as forms ticket should already exist
            //}

            string returnUrl = Request.QueryString["ReturnUrl"];

            if (returnUrl.IsEmpty())
            {
                Response.Redirect("~/");
            }
            else
            {
                Response.Redirect(returnUrl);
            }
        }

        public static string CreateTicketWithSecurityGroups(bool rememberMe, string username, string domain, int timeout)
    {
        using (var context = new PrincipalContext(ContextType.Domain, domain))
        {
            using (var principal = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username))
            {
                var securityGroups = String.Join(";", principal.GetAuthorizationGroups());

                var ticket =
                    new FormsAuthenticationTicket(1,
                                                  username,
                                                  DateTime.UtcNow,
                                                  DateTime.UtcNow.AddMinutes(timeout),
                                                  rememberMe,
                                                  securityGroups,
                                                  "/");

                string encTicket = FormsAuthentication.Encrypt(ticket);
                return encTicket;
            }
        }
    }

Dans IIS 7.5, cliquez sur les pages d'erreur, définissez la page 401 Chemin du fichier de fichier Redirect401.htm, avec ce code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
       <title></title>
        <script>
           window.location.assign('../Account/Signin');
      </script>
   </head>
  <body>

  </body>
   </html>

AccountController ...

public ActionResult SignIn()
    {
        return View(new SignInModel());
    }

    //
    // POST: /Account/SignIn

    [HttpPost]
    public ActionResult SignIn(SignInModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (Membership.ValidateUser(model.UserName, model.Password))
            {
                string encTicket = CreateTicketWithSecurityGroups(model.RememberMe,  model.UserName, model.Domain, FormsAuthentication.Timeout.Minutes);

                Response.Cookies.Add(new HttpCookie(".MVCAUTH", encTicket));

                //var returnUrl = "";
                for (var i = 0; i < Request.Cookies.Count; i++)
                {
                    HttpCookie cookie = Request.Cookies[i];
                    if (cookie.Name == ".MVCRETURNURL")
                    {
                        returnUrl = cookie.Value;
                        break;
                    }
                }

                if (returnUrl.IsEmpty())
                {
                    return Redirect("~/");
                }

                return Redirect(returnUrl);
            }

            ModelState.AddModelError("Log In Failure", "The username/password combination is invalid");
        }

        return View(model);
    }

    //
    // GET: /Account/SignOut

    public ActionResult SignOut()
    {
        FormsAuthentication.SignOut();

        if (Request.Cookies[".MVCRETURNURL"] != null)
        {
            var returnUrlCookie = new HttpCookie(".MVCRETURNURL") { Expires = DateTime.Now.AddDays(-1d) };
            Response.Cookies.Add(returnUrlCookie);
        }

        // Redirect back to sign in page so user can 
        //   sign in with different credentials

        return RedirectToAction("SignIn", "Account");

En global.asax:

protected void Application_BeginRequest(object sender, EventArgs e)
    {


        try
        {
            bool cookieFound = false;

            HttpCookie authCookie = null;

            for (int i = 0; i < Request.Cookies.Count; i++)
            {
                HttpCookie cookie = Request.Cookies[i];
                if (cookie.Name == ".MVCAUTH")
                {
                    cookieFound = true;
                    authCookie = cookie;
                    break;
                }
            }

            if (cookieFound)
            {
                // Extract the roles from the cookie, and assign to our current principal, which is attached to the HttpContext.
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
                HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(ticket), ticket.UserData.Split(';'));
            }



        }
        catch (Exception ex)
        {
            throw;
        }

    }


     protected void Application_AuthenticateRequest()
    {
        var returnUrl = Request.QueryString["ReturnUrl"];
        if (!Request.IsAuthenticated &&
            !String.IsNullOrWhiteSpace(returnUrl))
        {
            var returnUrlCookie = new HttpCookie(".MVCRETURNURL", returnUrl) {HttpOnly = true};
            Response.Cookies.Add(returnUrlCookie);
        }
    }

web.config

<!--<authorization>
  <deny users="?"/>
</authorization>-->
<authentication mode="Forms">
  <forms name=".MVCAUTH" loginUrl="~/WinLogin/WinLogin2.aspx" timeout="30" enableCrossAppRedirects="true"/>
</authentication>
<membership defaultProvider="AspNetActiveDirectoryMembershipProvider">
  <providers>
    <add name="AspNetActiveDirectoryMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider,           System.Web, Version=4.0.0.0, Culture=neutral,           PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADService" connectionProtection="Secure" enablePasswordReset="false" enableSearchMethods="true" requiresQuestionAndAnswer="true" applicationName="/" description="Default AD connection" requiresUniqueEmail="false" clientSearchTimeout="30" serverSearchTimeout="30" attributeMapPasswordQuestion="department" attributeMapPasswordAnswer="division" attributeMapEmail="mail" attributeMapUsername="sAMAccountName" maxInvalidPasswordAttempts="5" passwordAttemptWindow="10" passwordAnswerAttemptLockoutDuration="30" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1"/>
  </providers>
</membership><machineKey decryptionKey="..." validationKey="..." />  </system.web><connectionStrings> <add name="ADService" connectionString="LDAP://SERVER:389"/></connectionStrings>

http://msdn.microsoft.com/en-us /library/ms972958.aspx

Ce sera probablement vivre au fond de cette question et de ne jamais être trouvé, mais j'ai pu mettre en œuvre ce qui a été décrit à

http://mvolo.com / iis-70-twolevel-authentification avec formulaires d'authentification et-authentification windows /

Il était assez facile et triviale. N'a pas besoin de plusieurs applications ou hacks cookie, juste étendre le FormsAuthModule et faire quelques changements web.config.

Je sais que c'est un ancien poste - mais tout vit toujours sur internet

De toute façon, je devais déplacer un ancien site de IIS6 à IIS8. Ceci est un site de WebForms, mais je suppose que cette solution très simple est le même.

I reçu le message d'erreur:. Impossible de coulée objet de type 'System.Security.Principal.WindowsIdentity' taper 'System.Web.Security.FormsIdentity'

Tout ce que je ne faisais que créer un nouveau pool d'applications pour le site. Lors de la création, je mis le mode pipeline géré à « Classic ». (Lire la suite - http://www.hanselman.com/blog/MovingOldAppsFromIIS6ToIIS8AndWhyClassicModeExists.aspx) Ne pas oublier de mettre le pool d'applications du site à la nouvelle piscine, vous venez de créer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top