ASP.NET MVC में डायनामिक लॉगिन URL पर पुनर्निर्देशित कैसे करें


96

मैं एक मल्टी-टेनेंसी वेब साइट बना रहा हूं, जो क्लाइंट्स के लिए पेज होस्ट करती है। URL का पहला खंड एक स्ट्रिंग होगा जो क्लाइंट की पहचान करता है, जो निम्न URL रूटिंग योजना का उपयोग करके Global.asax में परिभाषित किया गया है:

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

यह ठीक काम करता है, URLs जैसे / foo / Home / Index।

हालांकि, [अधिकृत] विशेषता का उपयोग करते समय, मैं एक लॉगिन पृष्ठ पर पुनर्निर्देशित करना चाहता हूं जो समान मैपिंग योजना का उपयोग करता है। इसलिए यदि ग्राहक foo है, तो लॉगिन पेज web.config में निर्धारित / अकाउंट / लॉगइन रीडायरेक्ट के बजाय / foo / Account / Login होगा।

MVC 401 अनधिकृत स्थिति को वापस करने के लिए एक HttpUnauthorizedResult का उपयोग करता है, जिसे मैं ASP.NET वेब में परिभाषित पृष्ठ पर पुनर्निर्देशित करता है।

तो क्या किसी को पता है कि ASP.NET लॉग इन रीडायरेक्ट व्यवहार को कैसे ओवरराइड करना है? या कस्टम प्राधिकरण विशेषता बनाकर MVC में पुनर्निर्देशित करना बेहतर होगा?

EDIT - उत्तर: .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 }
                });
        }
    }
}

2
रूटिंग के साथ लगभग एक ही बात कर रहा है, इसलिए मुझे इसकी आवश्यकता है! धन्यवाद!
ट्रेवर डे कोएकोक

धन्यवाद, मैं यह पता लगाने की कोशिश कर रहा था कि कुछ इसी तरह कैसे करना है।
मौका

इसने मुझे खुद के कार्यान्वयन के लिए विचार दिया, बहुत बहुत धन्यवाद!
अलेक्जेंडर बेलेटस्की

3
MVC 2 और इसके बाद के संस्करण का उपयोग करके क्षेत्र = अशक्त (या सही क्षेत्र पर) सेट करना सुनिश्चित करें - या यह आपके द्वारा विज़िट किए गए पृष्ठ से विरासत में प्राप्त होगा
सिमोन_विवर

MVC के बिना ऐसा करने का कोई तरीका?
DARKGuy

जवाबों:


30

मुझे लगता है कि मुख्य मुद्दा यह है कि यदि आप अंतर्निहित ASP.NET FormsAuthentication वर्ग पर पिगबैक पर जा रहे हैं (और कोई अच्छा कारण नहीं है जो आपको नहीं करना चाहिए), दिन के अंत में कुछ कॉल करने जा रहा है FormsAuthentication.RedirectToLoginPage()जो कि जा रहा है एक कॉन्फ़िगर किए गए URL को देखने के लिए। केवल एक लॉगिन URL है, कभी भी, और बस इतना ही कि उन्होंने इसे कैसे डिज़ाइन किया है।

समस्या पर मेरा छुरा (संभवतः एक रब गोल्डबर्ग कार्यान्वयन) यह होगा कि वह सभी ग्राहकों द्वारा साझा किए गए रूट पर एक लॉगिन पृष्ठ पर रीडायरेक्ट करे, कहे / खाता / लॉगिन करे। यह लॉगिन पृष्ठ वास्तव में कुछ भी प्रदर्शित नहीं करेगा; यह या तो रिटर्नयूआरएल पैरामीटर या कुछ मूल्य का निरीक्षण करता है जो मुझे सत्र में मिला है या एक कुकी जो क्लाइंट की पहचान करता है और विशिष्ट / ग्राहक / खाते / लॉगिन पृष्ठ पर तत्काल 302 रीडायरेक्ट जारी करने के लिए उपयोग करता है। यह एक अतिरिक्त पुनर्निर्देश है, लेकिन ध्यान देने योग्य नहीं है और यह आपको पुनर्निर्देशन तंत्र में निर्मित का उपयोग करने देता है।

दूसरा विकल्प यह है कि आप अपनी स्वयं की कस्टम विशेषता बनाएं, जैसा कि आप वर्णन करते हैं और कक्षा में RedirectToLoginPage()विधि को कॉल करने वाली किसी भी चीज़ से बचते हैं FormsAuthentication, क्योंकि आप इसे अपने स्वयं के पुनर्निर्देशन तर्क के साथ बदल देंगे। (आप अपना स्वयं का वर्ग बना सकते हैं जो समान है।) चूंकि यह एक स्थिर वर्ग है, इसलिए मुझे किसी भी तंत्र के बारे में पता नहीं है, जिसके द्वारा आप अपने स्वयं के वैकल्पिक इंटरफ़ेस को इंजेक्ट कर सकते हैं और इसे मौजूदा [अधिकृत] विशेषता के साथ जादुई रूप से काम करते हैं, जो मारपीट करता है, लेकिन लोगों ने पहले भी ऐसा ही किया है

उम्मीद है की वो मदद करदे!


यह शायद सबसे सुरक्षित तरीका है। अपनी खुद की [MyAuthorize] विशेषता बनाना खतरनाक है। जब तक आपका बिल्ड यह सत्यापित नहीं कर रहा है कि लोग अंतर्निहित [अधिकृत] का उपयोग नहीं करते हैं, तो आप लोगों को (या अपने आप को) भूल जाने और गलत का उपयोग करने का श्रेय देते हैं
Simon_Weaver

कुछ मामलों में Application_AuthenticateRequestहालांकि यह ओवरराइड करने में मददगार हो सकता है (नीचे मेरा जवाब देखें)।
टर्दस-मेरुला

41

ASP.NET MVC के RTM संस्करण में, रद्द की गई संपत्ति गायब है। यह कोड 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 }
                        });
            }
        }
    }
}

संपादित करें: आप web.config में डिफ़ॉल्ट प्रपत्र प्रमाणीकरण loginUrl को निष्क्रिय करना चाह सकते हैं - यदि कोई व्यक्ति भूल जाता है कि आपके पास एक कस्टम विशेषता है और गलती से [अधिकृत] विशेषता में निर्मित का उपयोग करता है।

Web.config में मान को संशोधित करें:

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

फिर एक एक्शन विधि 'ERROR' बनाएं जो एक त्रुटि को लॉग करता है और उपयोगकर्ता को आपके पास मौजूद सबसे सामान्य लॉगिन पेज पर रीडायरेक्ट करता है।


2
MVC 2 और इसके बाद के संस्करण में शब्दकोश में (या अपने क्षेत्र को जो भी कहा जाता है) को {क्षेत्र, अशक्त} जोड़ना सुनिश्चित करें - या यह आपके द्वारा विज़िट किए गए पृष्ठ से विरासत में प्राप्त होगा
Simon_Weaver

2

इस समस्या का मेरा समाधान एक कस्टम 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; }
    }

0

फिर भी, यदि किसी एक का उपयोग करने का फैसला करता निर्मित ASP.NET FormsAuthentication, एक overide कर सकते हैं 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;
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.