Domanda

Ho uno scenario in cui mi richiedono agli utenti di essere in grado di autenticare contro un'applicazione web ASP.NET MVC utilizzando l'autenticazione di Windows o l'autenticazione Forms. Se l'utente si trova sulla rete interna useranno autenticazione di Windows e se si collegano esternamente useranno autenticazione Forms. Ho visto abbastanza poche persone porre la domanda come faccio a configurare un'applicazione web ASP.NET MVC per questo, ma non ho trovato una spiegazione completa.

Per favore qualcuno può presentare una spiegazione dettagliata, con esempi di codice, su come questo sarebbe stato fatto?

Grazie.

Alan T

È stato utile?

Soluzione

Questo è chiamato mista modalità di autenticazione . In pratica non è possibile ottenere questo all'interno di un unica di domanda, perché in IIS una volta che si imposta l'autenticazione di Windows per una directory virtuale che non accetterà più utenti di diversi domini. Quindi, in pratica è necessario avere due applicazioni, la prima con l'autenticazione di Windows e la seconda (l'applicazione principale) che utilizzano l'autenticazione Forms. La prima applicazione sarà costituito da un unico indirizzo che si limiterà a reindirizzare l'applicazione principale mediante l'emissione di un ticket di autenticazione per l'utente di dominio.

Altri suggerimenti

Questo può essere fatto. Invertire la configurazione, impostare l'applicazione / root per usare anonimo e Autenticazione moduli ... In questo modo, è possibile configurare l'autenticazione mista all'interno della stessa applicazione web, ma è difficile. Quindi, prima, si configurare app per autenticazione basata su form con loginUrl = "~ / WinLogin / WinLogin2.aspx". In MVC, il routing ignora le regole di autenticazione stabilite da IIS, quindi è necessario utilizzare una pagina aspx, come IIS può impostare l'autenticazione sul file. Abilita anonimo e autenticazione basata su form sull'applicazione web root. Abilita autenticazione di Windows e disabilitare l'autenticazione anonima nella directory root / WinLogin. Aggiungere 401.2 pagine di errore personalizzate 401 e per reindirizzare indietro al Conto / Signin URL.

Questo permetterà a qualsiasi browser in grado di pass-through per utilizzare integrata di Windows l'autenticazione per signin automatico. Mentre alcuni dispositivi avranno richieste le credenziali (come iPhone) e altri dispositivi come BlackBerry reindirizzato alla pagina di accesso.

Questo crea anche un cookie aggiungendo esplicitamente i ruoli degli utenti e crea un principio generico in modo che l'autorizzazione basata sui ruoli può essere utilizzato.

in WinLogin2.aspx (nella directory WinLogin in "root" web application in IIS, e configurato per utilizzare l'autenticazione di Windows, anonimo disabili, e le forme abilitato (come non può spegnere ... notare IIS si lamentano quando si abilita autenticazione di Windows, semplicemente ignorare):

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;
            }
        }
    }

In IIS 7.5, fare clic su pagine di errore, impostare la pagina 401 di percorso del file Redirect401.htm file, con questo codice:

<!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>

In 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");

In 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

Questa sarà probabilmente vive in fondo a questa domanda e non essere trovato, ma sono stato in grado di realizzare ciò che è stato descritto a

http://mvolo.com / iis-70-twolevel-autenticazione-con-forme-authentication-e-windows-autenticazione /

E 'stato abbastanza facile e banale. Non ha bisogno di più applicazioni o hack biscotto, basta estendere la FormsAuthModule e fare alcune modifiche web.config.

So che questo è un vecchio post - ma tutto vive per sempre su internet

!

In ogni caso, ho dovuto spostare un vecchio sito web da IIS6 a IIS8. Questo è un sito web WebForms, ma suppongo questo molto semplice soluzione è la stessa.

Ho ricevuto l'errore:. Impossibile eseguire il cast oggetto di tipo 'System.Security.Principal.WindowsIdentity' digitare 'System.Web.Security.FormsIdentity'

Tutto quello che ho fatto è stato creare un nuovo pool di applicazioni per il sito web. Durante la creazione di questo, ho impostato la modalità pipeline gestite al 'Classic'. (Per saperne di più qui - http://www.hanselman.com/blog/MovingOldAppsFromIIS6ToIIS8AndWhyClassicModeExists.aspx) Non dimenticate di impostare pool di applicazioni del sito web per la nuova piscina che avete appena creato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top