2010-04-07 25 views
14

हमारे पास एक आंतरिक एएसपी.नेट एमवीसी एप्लीकेशन है जिसके लिए लॉगऑन की आवश्यकता होती है। लॉग ऑन महान काम करता है और क्या अपेक्षित है। हमारे पास 15 मिनट का सत्र समाप्ति है। उस अवधि के लिए एक पृष्ठ पर बैठने के बाद, उपयोगकर्ता ने सत्र खो दिया है। यदि वे वर्तमान पृष्ठ को रीफ्रेश करने या किसी अन्य पर ब्राउज़ करने का प्रयास करते हैं, तो उन्हें पृष्ठ पर एक लॉग मिलेगा। हम उनके अनुरोध को संग्रहीत करते हैं ताकि वे लॉग इन करने के बाद वे उस पृष्ठ पर जारी रह सकें जिस पर उन्होंने अनुरोध किया है। यह बहुत अच्छा काम करता है।एएसपी.नेट एमवीसी सत्र समाप्ति

हालांकि, मेरी समस्या यह है कि कुछ पृष्ठों पर AJAX कॉल हैं। उदाहरण के लिए, वे एक फॉर्म का हिस्सा भर सकते हैं, भटक सकते हैं और अपना सत्र समाप्त कर सकते हैं। जब वे वापस आते हैं, तो स्क्रीन अभी भी प्रदर्शित होती है। अगर वे बस एक बॉक्स भरते हैं (जो एक एजेक्स कॉल करेगा) AJAX कॉल लॉगऑन पेज लौटाएगा (AJAX को जो भी div चाहिए वह वास्तव में वास्तविक परिणाम लौटाएगा)। यह भयानक लग रहा है।

मुझे लगता है कि समाधान पेज की अवधि स्वयं समाप्त करने के लिए (ताकि जब एक सत्र समाप्त हो जाता है, वे स्वतः लॉगऑन स्क्रीन करने के लिए उनके द्वारा किए बिना किसी लौटा दिया जाता है) है। हालांकि, मैं सोच रहा हूं कि एएसपी.नेट एमवीसी में सर्वोत्तम प्रथाओं के संबंध में विशेष रूप से इसे कैसे कार्यान्वित किया जाए, इस पर राय/विचार हैं।

अद्यतन:

तो मैं आगे चला गया और मेरी OnActionExecuting (प्रति Keltex के सुझाव)

if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
    { 
    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    { 
     filterContext.HttpContext.Response.Write("Invalid session -- please login!"); 
     filterContext.HttpContext.Response.End(); 
    } 
    else 
    { 
     ... 
    } 
    } 

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

मैं अब भी लगता है कि मैं के साथ-साथ कि womp सुझाव जावास्क्रिप्ट उलटी गिनती लागू करेंगे।

+0

@Andrew - यह एक सुरुचिपूर्ण समाधान है। वैकल्पिक रूप से, फ़िल्टर Context.HttpContext.Response.Redirect ("/ error/xxx") होगा; (या कुछ) काम करते हैं? – Keltex

+0

@ केल्टेक्स: जैसा कि आप सुझाव देते हैं, मैं इसे एक दृश्य में ले जा सकता हूं - लेकिन मेरे कई AJAX कॉल में, वे कच्चे डेटा (मूल्यों की सूची जैसे) को वापस नहीं कर रहे हैं, जबकि कोई HTML नहीं है जबकि अन्य में वे शायद एक पूरी तालिका लौट रहे हैं अच्छी तरह से स्वरूपित डेटा का।तो सिर्फ कच्चे डेटा का "सबसे कम आम denominator" सबसे अच्छा काम कर सकता है। मैं इसके साथ खेलूँगा। –

उत्तर

16

विशेष रूप से, मुझे नहीं पता कि इसके बारे में कोई भी सर्वोत्तम प्रथाएं हैं, लेकिन मैं अभी हमारे ऐप के लिए यह कर रहा हूं। हमने क्लाइंट-साइड समाधान का चयन किया है जहां हम मास्टर पेज में कुछ जावास्क्रिप्ट में सत्र टाइमआउट मान आउटपुट करते हैं, और सत्र की अवधि समाप्त होने पर गणना करते हैं।

हाथ से 5 मिनट पहले, हम एक मोडल डायलॉग बॉक्स पॉप अप करते हुए कहते हैं, "क्या आप अभी भी वहां हैं?" उलटी गिनती टाइमर के साथ। एक बार जब टाइमर 00:00 मारता है, हम प्रवेश पृष्ठ पर ब्राउज़र अनुप्रेषित।

यह समय और टाइमर गणना करने के लिए जावास्क्रिप्ट की न्यूनतम मात्रा के साथ कार्यान्वित किया गया है, और एक साधारण .ashx हैंडलर जो सत्र को रीफ्रेश करेगा यदि उपयोगकर्ता "मैं वापस आ गया हूं" क्लिक करता हूं सत्र समाप्त होने से पहले संवाद बॉक्स पर। इस तरह यदि वे समय पर वापस आते हैं, तो वे बिना किसी नेविगेशन के सत्र को रीफ्रेश कर सकते हैं।

+2

+1: प्रत्येक अनुरोध के साथ सत्र की जांच करने से यह कम प्रभाव वाला, कम-कोड समाधान होगा। –

+2

यह बहुत अच्छा है। मैं पूरी तरह से इसे पकड़ने जा रहा हूँ। – Will

+0

क्या देखना था "gank" का मतलब था ... :-) मुझे लगता है कि मैं इसे लागू करने जा रहा हूं और साथ ही केल्टेक्स के सुझाव के अनुसार कुछ AJAX सुरक्षा प्रदान करता हूं। धन्यवाद! –

2

आप अजाक्सऑप्शन में देख सकते हैं जिन्हें अजाक्स.बिनगॉर्म() में सेट किया जा सकता है। एक ऑनबिन सेटिंग है जिसे आप जावास्क्रिप्ट फ़ंक्शन से जोड़ सकते हैं, जो यह पुष्टि करने के लिए नियंत्रक विधि को कॉल कर सकता है कि सत्र अभी भी वैध है, और यदि नहीं, तो window.location का उपयोग करके लॉगिन पृष्ठ पर रीडायरेक्ट करें।

1

समस्या का एक हिस्सा यह प्रतीत होता है कि आप ढांचे को सब कुछ करने दे रहे हैं। मैं आपकी AJAX विधि को [Authorize] विशेषता के साथ सजाने नहीं दूंगा। इसके बजाय User.Identity.IsAuthenticated जांचें और यदि यह गलत लौटाता है, तो समझदार त्रुटि संदेश बनाएं।

+0

धन्यवाद! मैंने इसे OnActionExecuting में लागू किया (ऊपर देखें)। –

+0

अधिकृत विशेषता ठीक है, लेकिन आपको इसे ठीक से संशोधित करना होगा। 'User.Identity.Is प्रमाणीकृत 'की जांच करना वही नहीं है। – LukLed

7

मैंने कल इसी तरह के प्रश्न पूछा।,

public class OptionalAuthorizeAttribute : AuthorizeAttribute 
{ 
    private class Http403Result : ActionResult 
    { 
     public override void ExecuteResult(ControllerContext context) 
     { 
      // Set the response code to 403. 
      context.HttpContext.Response.StatusCode = 403; 
      context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue); 
     } 
    } 

    private readonly bool _authorize; 

    public OptionalAuthorizeAttribute() 
    { 
     _authorize = true; 
    } 

    //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. 
    //That is why parameter is introduced. 
    public OptionalAuthorizeAttribute(bool authorize) 
    { 
     _authorize = authorize; 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     //When authorize parameter is set to false, not authorization should be performed. 
     if (!_authorize) 
      return true; 

     var result = base.AuthorizeCore(httpContext); 

     return result; 
    } 

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) 
     { 
      //Ajax request doesn't return to login page, it just returns 403 error. 
      filterContext.Result = new Http403Result(); 
     } 
     else 
      base.HandleUnauthorizedRequest(filterContext); 
    } 
} 

HandleUnauthorizedRequest ओवरराइड की गई है तो यह Http403Result लौटाता है जब अजाक्स का उपयोग:

संशोधित अधिकृत विशेषता: यहाँ मेरी समाधान है। Http403Result स्थिति कोड को 403 में बदलता है और प्रतिक्रिया में उपयोगकर्ता को संदेश देता है। विशेषता (authorize पैरामीटर) में कुछ अतिरिक्त तर्क हैं, क्योंकि मैं आधार नियंत्रक में [Authorize] चालू करता हूं और इसे कुछ पृष्ठों में अक्षम करता हूं।

अन्य महत्वपूर्ण हिस्सा ग्राहक पक्ष पर इस प्रतिक्रिया का वैश्विक प्रबंधन है। यह है कि मैं क्या Site.Master में रखा है:

<script type="text/javascript"> 
    $(document).ready(
     function() { 
      $("body").ajaxError(
       function(e,request) { 
        if (request.status == 403) { 
         alert(request.responseText); 
         window.location = '/Logout'; 
        } 
       } 
      ); 
     } 
    ); 
</script> 

मैं जगह वैश्विक ajax त्रुटि हैंडलर और जब एवर्ट $.post 403 त्रुटि के साथ विफल, प्रतिक्रिया संदेश को सतर्क कर दिया है और उपयोगकर्ता पेज लॉगआउट पर भेज दिया जाएगा। अब मुझे हर $.post अनुरोध में त्रुटि को संभालने की आवश्यकता नहीं है, क्योंकि इसे वैश्विक रूप से संभाला जाता है।

क्यों 403, 401 नहीं? 401 एमवीसी फ्रेमवर्क द्वारा आंतरिक रूप से संभाला जाता है (यही कारण है कि लॉगिन पृष्ठ पर पुनर्निर्देशन विफल प्राधिकरण के बाद किया जाता है)।

आप इसके बारे में क्या सोचते हैं?

संपादित करें:

[अधिकृत] विशेषता से इस्तीफा देने के बारे में: [अधिकृत] न केवल Identity.IsAuthenticated जाँच के बारे में है। यह पृष्ठ कैशिंग को भी संभालता है (इसलिए आप उस सामग्री को कैश नहीं करते हैं जिसके लिए प्रमाणीकरण की आवश्यकता होती है) और पुनर्निर्देशन। इस कोड को कॉपी करने की कोई आवश्यकता नहीं है।

0

मेरा समाधान लॉगिन फ़ॉर्म पर एक मेटा टैग और जावास्क्रिप्ट/jQuery का थोड़ा सा उपयोग करता है।

LogOn.cshtml

<html> 
    <head> 
    <meta data-name="__loginform__" content="true" /> 
    ... 
    </head> 
    ... 
</html> 

Common.js

var Common = { 
    IsLoginForm: function (data) { 
     var res = false; 

     if (data.indexOf("__loginform__") > 0) { 
      // Do a meta-test for login form 
      var temp = 
       $("<div>") 
        .html(data) 
        .find("meta[data-name='__loginform__']") 
        .attr("content"); 

      res = !!temp; 
     } 
     return res; 
    } 
}; 

AJAX कोड

$.get(myUrl, myData, function (serverData) { 
    if (Common.IsLoginForm(serverData)) { 
     location.reload(); 
     return; 
    } 

    // Proceed with filling your placeholder or whatever you do with serverData response 
    // ... 
}); 
0

यहाँ कैसे मैंने किया है .. ।

मेरी आधार नियंत्रक में

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      if (filterContext.HttpContext.Request.IsAjaxRequest()) 
      { 
       filterContext.HttpContext.Response.StatusCode = 403; 
       filterContext.HttpContext.Response.Write(SessionTimeout); 
       filterContext.HttpContext.Response.End(); 
      } 
     } 
    } 

तब मेरे वैश्विक .js में दाखिल

$.ajaxSetup({ 
error: function (x, status, error) { 
    if (x.status == 403) { 
     alert("Sorry, your session has expired. Please login again to continue"); 
     window.location.href = "/Account/Login"; 
    } 
    else { 
     alert("An error occurred: " + status + "nError: " + error); 
    } 
} 

});

सत्र टाइमआउट चर एक नोटरी स्ट्रिंग है। मैंने ब्रेवटी के लिए कार्यान्वयन को छोड़ दिया।

संबंधित मुद्दे