كيفية إعادة التوجيه إلى عنوان URL لتسجيل الدخول الديناميكي في ASP.NET MVC

StackOverflow https://stackoverflow.com/questions/356982

سؤال

أقوم بإنشاء موقع ويب متعدد الإيجارات يستضيف صفحات للعملاء.سيكون الجزء الأول من عنوان URL عبارة عن سلسلة تحدد العميل، ويتم تعريفها في Global.asax باستخدام نظام توجيه URL التالي:

"{client}/{controller}/{action}/{id}"

يعمل هذا بشكل جيد مع عناوين URL مثل /foo/Home/Index.

ومع ذلك، عند استخدام السمة [Authorize]، أريد إعادة التوجيه إلى صفحة تسجيل الدخول التي تستخدم أيضًا نفس نظام التعيين.لذا، إذا كان العميل هو foo، فستكون صفحة تسجيل الدخول هي /foo/Account/Login بدلاً من إعادة التوجيه الثابتة /Account/Login المحددة في web.config.

يستخدم MVC HttpUnauthorizedResult لإرجاع الحالة غير المصرح بها 401، والتي أفترض أنها تؤدي إلى إعادة توجيه ASP.NET إلى الصفحة المحددة في web.config.

فهل يعرف أي شخص كيفية تجاوز سلوك إعادة توجيه تسجيل الدخول إلى ASP.NET؟أم أنه من الأفضل إعادة التوجيه في MVC عن طريق إنشاء سمة ترخيص مخصصة؟

تحرير - الإجابة: بعد بعض البحث في مصدر .Net، قررت أن سمة المصادقة المخصصة هي الحل الأفضل:

public class ClientAuthorizeAttribute: AuthorizeAttribute
{
    public override void OnAuthorization( AuthorizationContext filterContext )
    {
        base.OnAuthorization( filterContext );

        if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary
                {
                    { "client", filterContext.RouteData.Values[ "client" ] },
                    { "controller", "Account" },
                    { "action", "Login" },
                    { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                });
        }
    }
}
هل كانت مفيدة؟

المحلول

أعتقد أن المشكلة الرئيسية هي أنه إذا كنت ستستخدم فئة ASP.NET FormsAuthentication المضمنة (وليس هناك سبب وجيه يمنعك من ذلك)، فسوف يستدعيك شيء ما في نهاية اليوم FormsAuthentication.RedirectToLoginPage() والذي سوف ينظر إلى عنوان URL الذي تم تكوينه.لا يوجد سوى عنوان URL واحد لتسجيل الدخول على الإطلاق، وهذه هي الطريقة التي صمموها بها.

تتمثل محاولتي في حل المشكلة (ربما تنفيذ Rube Goldberg) في السماح لها بإعادة التوجيه إلى صفحة تسجيل دخول واحدة في الجذر المشترك بين جميع العملاء، على سبيل المثال /account/login.لن تعرض صفحة تسجيل الدخول هذه أي شيء فعليًا؛يقوم بفحص إما معلمة ReturnUrl أو بعض القيم التي حصلت عليها في الجلسة أو ملف تعريف الارتباط الذي يحدد العميل ويستخدم ذلك لإصدار إعادة توجيه 302 فورية إلى صفحة /client/account/login المحددة.إنها عملية إعادة توجيه إضافية، ولكن من المحتمل ألا تكون ملحوظة وتتيح لك استخدام آليات إعادة التوجيه المضمنة.

الخيار الآخر هو إنشاء السمة المخصصة الخاصة بك كما تصفها وتجنب أي شيء يستدعي RedirectToLoginPage() الطريقة على FormsAuthentication class، نظرًا لأنك ستستبدله بمنطق إعادة التوجيه الخاص بك.(يمكنك إنشاء فئتك الخاصة المشابهة.) نظرًا لأنها فئة ثابتة، فأنا لست على علم بأي آلية يمكنك من خلالها إدخال الواجهة البديلة الخاصة بك وجعلها تعمل بطريقة سحرية مع السمة [Authorize] الموجودة، والتي ضربات ولكن لقد فعل الناس أشياء مماثلة من قبل.

امل ان يساعد!

نصائح أخرى

في إصدار RTM من ASP.NET MVC، خاصية الإلغاء مفقودة.يعمل هذا الرمز مع ASP.NET MVC RTM:

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Resources;

namespace ePegasus.Web.ActionFilters
{
    public class CustomAuthorize : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            if (filterContext.Result is HttpUnauthorizedResult)
            {
                filterContext.Result = new RedirectToRouteResult(
                    new System.Web.Routing.RouteValueDictionary
                        {
                                { "langCode", filterContext.RouteData.Values[ "langCode" ] },
                                { "controller", "Account" },
                                { "action", "Login" },
                                { "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
                        });
            }
        }
    }
}

يحرر: قد ترغب في تعطيل مصادقة النماذج الافتراضية (loginUrl) في web.config - في حالة نسي شخص ما أن لديك سمة مخصصة واستخدم السمة [Authorize] المضمنة عن طريق الخطأ.

قم بتعديل القيمة في web.config:

 <forms loginUrl="~/Account/ERROR" timeout="2880" />

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

كان الحل الخاص بي لهذه المشكلة هو العرف ActionResult فصل:

    sealed public class RequiresLoginResult : ActionResult
    {
        override public void ExecuteResult (ControllerContext context)
        {
            var response = context.HttpContext.Response;

            var url = FormsAuthentication.LoginUrl;
            if (!string.IsNullOrWhiteSpace (url))
                url += "?returnUrl=" + HttpUtility.UrlEncode (ReturnUrl);

            response.Clear ();
            response.StatusCode = 302;
            response.RedirectLocation = url;
        }

        public RequiresLoginResult (string returnUrl = null)
        {
            ReturnUrl = returnUrl;
        }

        string ReturnUrl { get; set; }
    }

ومع ذلك، إذا قرر أحد استخدام ASP.NET FormsAuthentication المضمن، فيمكنه تجاوز ذلك Application_AuthenticateRequest في Global.asax.cs على النحو التالي:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    string url = Request.RawUrl;

    if (url.Contains(("Account/Login"))
    {
        return;
    }

    if (Context.User == null)
    {
        // Your custom tenant-aware logic
        if (url.StartsWith("/foo"))
        {
            // Your custom login page.
            Response.Redirect("/foo/Account/Login");
            Response.End();
            return;
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top