سؤال

لدي سيناريو حيث أطلب من المستخدمين أن أكون قادرا على المصادقة ضد تطبيق ويب ASP.NET MVC باستخدام مصادقة Windows أو مصادقة النماذج. إذا كان المستخدم موجودا على الشبكة الداخلية، فسوف يستخدمون مصادقة Windows وإذا كانوا يتصلون خارجيا، فسوف يستخدمون مصادقة النماذج. لقد رأيت عددا قليلا من الأشخاص الذين يطرحون السؤالين كيف يمكنني تكوين تطبيق ويب ASP.NET MVC لهذا، لكنني لم أجد تفسيرا كامل.

من فضلك، هل يمكن لشخص ما تقديم شرح مفصل، مع أمثلة التعليمات البرمجية، كيف سيتم ذلك؟

شكرا.

آلان ت

هل كانت مفيدة؟

المحلول

هذا يسمي وضع المصادقة المختلطة. وبعد أساسا لا يمكنك تحقيق ذلك داخل غير مرتبطة تطبيق لأنه في IIS بمجرد إعداد مصادقة Windows للحصول على دليل ظاهري لن يقبل المستخدمين من مجالات مختلفة. لذلك، تحتاج في الأساس إلى وجود تطبيقين، الأول مع مصادقة Windows والثاني (التطبيق الرئيسي) باستخدام مصادقة النماذج. سيتألف التطبيق الأول من عنوان واحد سيعيد توجيهه ببساطة إلى التطبيق الرئيسي عن طريق إصدار تذكرة مصادقة لمستخدم المجال.

نصائح أخرى

يمكن القيام بذلك. عكس التكوين، قم بتعيين التطبيق / الجذر لاستخدام مصادقة مجهول ونماذج ... بهذه الطريقة، يمكنك تكوين المصادقة المختلطة داخل تطبيق الويب نفسه، لكنه صعب. أولا أولا، قم بتكوين تطبيق لك مصادقة النماذج مع Loginurl = "~ / winlogin / winlogin2.aspx". في MVC، يتجاوز قواعد المصادقة التي تحددها IIS، لذلك تحتاج إلى استخدام صفحة ASPX، حيث يمكن IIS تعيين المصادقة على الملف. تمكين المصادقة المجهولة والنماذج على تطبيق جذر الويب. تمكين مصادقة Windows وتعطيل المصادقة المجهولة في دليل الجذر / WinLogin. أضف مخصص 401 و 401.2 صفحات الخطأ لإعادة توجيه العودة إلى حساب URL / Signin.

سيسمح ذلك بأي متصفح قادر على استخدام المصادقة المتكاملة ل Windows مع Signin Auto. في حين أن بعض الأجهزة ستحصل على بيانات الاعتماد (مثل iPhone) وغيرها من الأجهزة مثل BlackBerry Redirected To Signin Page.

يقوم هذا أيضا بإنشاء ملف تعريف ارتباط إضافي يقوم بإضافة أدوار المستخدمين بشكل صريح وإنشاء مبدأ عام بحيث يمكن استخدام إذن يستند إلى الدور.

في Winlogin2.aspx (في دليل Winlogin ضمن تطبيق الويب "الجذر" في IIS، وتم تكوينه لاستخدام مصادقة Windows، ومعطل مجهول، وتمكين النماذج (كما لا يمكن إيقاف تشغيل ... ملاحظة IIS ستشكو عند تمكين مصادقة Windows، فقط تجاهل):

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

في IIS 7.5، انقر فوق صفحات الخطأ، اضبط صفحة 401 على مسار ملف Redirect401.htm، مع هذا الرمز:

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

في 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.

من المحتمل أن يعيش هذا في أسفل هذا السؤال وعدم العثور عليه، لكنني كنت قادرا على تنفيذ ما هو موضح في

http://mvolo.com/iis-70-twoleventication-with-forms-Authentication-and-windows-Authentication/

كان من السهل جدا وتافهة. لم يحتاج إلى تطبيقات متعددة أو خارقة ملفات تعريف الارتباط، فقط تمديد النماذج الأولية وإجراء بعض التغييرات Web.config.

أعلم أن هذا ما بعد القديم - لكن كل شيء يعيش إلى الأبد على الإنترنت!

على أي حال، اضطررت إلى نقل موقع ويب قديم من IIS6 إلى IIS8. هذا هو موقع WebForms، لكنني أفترض أن هذا الحل البسيط للغاية هو نفسه.

تلقيت الخطأ: غير قادر على إلقاء كائن من النوع "system.security.principal.windowsInditity" لنوع "system.web.security.formsidentity".

كل ما فعلته هو إنشاء تجمع تطبيق جديد للموقع. عند إنشاء هذا، قمت بتعيين وضع خط الأنابيب المدار إلى "الكلاسيكية". (اقرأ المزيد هنا - http://www.hanselman.com/blog/movingoldappsfromiis6toiis8andwhyclassicmodexist.aspx.) لا تنسى تعيين تجمع تطبيقات الموقع إلى البركة الجديدة التي أنشأتها للتو.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top