2010-07-26 11 views
22

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

तो मैं इस स्थिति को संभालना चाहता हूं। मुझे पता है कि कुछ लोग AJAX प्रमाणीकरण का उपयोग करते हैं, लेकिन मुझे यकीन नहीं है कि यह मेरे लिए उपयुक्त है क्योंकि यह मेरे लिए काफी जटिल दिखता है और मेरा एप्लिकेशन पहले लॉग इन किए बिना किसी भी एक्सेस की अनुमति नहीं देता है। मैं केवल सभी AJAX प्रतिक्रियाओं के लिए एक वैश्विक हैंडलर लिखना चाहता हूं जो हमें window.location.reload() करेगा यदि हमें प्रमाणित करने की आवश्यकता है। मुझे लगता है कि इस मामले में मानक लॉगिन फॉर्म के बजाय 401 त्रुटि प्राप्त करना बेहतर है क्योंकि इसे संभालना आसान है।

तो,

1) यह सब jQuery ajax अनुरोध के लिए वैश्विक त्रुटि हैंडलर लिखने के लिए संभव है?

2) मैं AJAX अनुरोधों के लिए 401 त्रुटि भेजने के लिए वसंत-सुरक्षा के व्यवहार को कैसे अनुकूलित कर सकता हूं लेकिन नियमित रूप से सामान्य लॉगिन पृष्ठ को सामान्य अनुरोध दिखाने के लिए?

3) क्या आपके पास अधिक सुन्दर समाधान हो सकता है? कृपया इसे साझा करें।

धन्यवाद।

+0

यह कुछ समय हो गया है जब आपने यह पूछा था। क्या आप अपने आप को एक अच्छे समाधान के साथ आ गए हैं? –

+1

मैंने हाल ही में इस मुद्दे पर एक ब्लॉग पोस्ट लिखा है: http://www.to-string.com/2012/08/03/springsecurity-authenticating-authorizing-ajax-requests/ – craftsman

+0

मुझे @craftsman समाधान पसंद है। मैंने इसे सरल भी बनाया (कम से कम मुझे ऐसा लगता है)। Http://gedrox.blogspot.com/2013/03/blog-post.html देखें। – Gedrox

उत्तर

2

यहां मैं आमतौर पर इसे कैसे करता हूं। प्रत्येक AJAX कॉल पर, इसका उपयोग करने से पहले परिणाम की जांच करें।

$.ajax({ type: 'GET', 
    url: GetRootUrl() + '/services/dosomething.ashx', 
    success: function (data) { 
     if (HasErrors(data)) return; 

     // process data returned... 

    }, 
    error: function (xmlHttpRequest, textStatus) { 
     ShowStatusFailed(xmlHttpRequest); 
    } 
    }); 

और फिर HasErrors() समारोह इस तरह दिखता है, और सभी पृष्ठों पर साझा किया जा सकता।

function HasErrors(data) { 
    // check for redirect to login page 
    if (data.search(/login\.aspx/i) != -1) { 
    top.location.href = GetRootUrl() + '/login.aspx?lo=TimedOut'; 
    return true; 
    } 
    // check for IIS error page 
    if (data.search(/Internal Server Error/) != -1) { 
    ShowStatusFailed('Server Error.'); 
    return true; 
    } 
    // check for our custom error handling page 
    if (data.search(/Error.aspx/) != -1) { 
    ShowStatusFailed('An error occurred on the server. The Technical Support Team has been provided with the error details.'); 
    return true; 
    } 
    return false; 
} 
3

मैं अभी इस समस्या के समाधान के साथ आया हूं, लेकिन इसे पूरी तरह से परीक्षण नहीं किया है। मैं वसंत, वसंत सुरक्षा, और jQuery का भी उपयोग कर रहा हूं। सबसे पहले, अपना लॉगिन के नियंत्रक से, मैं 401 के लिए स्थिति कोड सेट करें:

LoginController { 

public ModelAndView loginHandler(HttpServletRequest request, HttpServletResponse response) { 

... 
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
... 
return new ModelAndView("login", model); 
} 

उनके ऑनलोड में() विधियों, अपने पृष्ठों के सभी मेरे वैश्विक जावास्क्रिप्ट फ़ाइल में एक समारोह फोन:

function initAjaxErrors() { 

jQuery(window).ajaxError(function(event, xmlHttpRequest, ajaxOptions, thrownError) { 
    if (403 == xmlHttpRequest.status) 
     showMessage("Permission Denied"); 
    else 
     showMessage("An error occurred: "+xmlHttpRequest.status+" "+xmlHttpRequest.statusText); 
}); 

}

इस बिंदु पर, आप जिस तरह से चाहें 401 त्रुटि को संभाल सकते हैं। एक प्रोजेक्ट में, मैंने लॉगिन फॉर्म वाले आईफ्रेम के चारों ओर एक jQuery संवाद डालकर jQuery प्रमाणीकरण को संभाला है।

4

http://forum.springsource.org/showthread.php?t=95881 पर एक नजर डालें, मुझे लगता है कि प्रस्तावित समाधान अन्य उत्तर यहाँ की तुलना में बहुत स्पष्ट है:

  1. अपने jQuery ajax कॉल में एक कस्टम हेडर जोड़ें ('beforeSend' हुक का प्रयोग करके)। आप jQuery द्वारा भेजे गए "एक्स-अनुरोधित-साथ" हेडर का भी उपयोग कर सकते हैं।
  2. उपयोगकर्ता पक्ष में उस शीर्षलेख को देखने के लिए स्प्रिंग सुरक्षा कॉन्फ़िगर करें ताकि उपयोगकर्ता को लॉगिन पृष्ठ पर ले जाने के बजाय HTTP 401 त्रुटि कोड लौटाया जा सके।
+1

और यदि कोई '$ .getJSON() {...}' का उपयोग करता है तो क्या होगा? "पहले भेजो" तो संभव नहीं है। – zygimantus

10

यहां एक ऐसा दृष्टिकोण है जो मुझे लगता है कि यह काफी सरल है। यह उन दृष्टिकोणों का एक संयोजन है जो मैंने इस साइट पर देखा है।मैंने इसके बारे में एक ब्लॉग पोस्ट लिखा: http://yoyar.com/blog/2012/06/dealing-with-the-spring-security-ajax-session-timeout-problem/

मूलभूत विचार एक एपीआई यूआरएल उपसर्ग (यानी/एपीआई/सुरक्षित) का उपयोग करना है जैसा ऊपर दिया गया है प्रमाणीकरण प्रविष्टि बिंदु के साथ। यह आसान है और काम करता है।

यहाँ प्रमाणीकरण प्रवेश बिंदु है:

package com.yoyar.yaya.config; 

import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; 

import javax.servlet.ServletException; 
import javax.servlet.http.*; 
import java.io.IOException; 

public class AjaxAwareAuthenticationEntryPoint 
      extends LoginUrlAuthenticationEntryPoint { 

    public AjaxAwareAuthenticationEntryPoint(String loginUrl) { 
     super(loginUrl); 
    } 

    @Override 
    public void commence(
     HttpServletRequest request, 
     HttpServletResponse response, 
     AuthenticationException authException) 
      throws IOException, ServletException { 

     boolean isAjax 
      = request.getRequestURI().startsWith("/api/secured"); 

     if (isAjax) { 
      response.sendError(403, "Forbidden"); 
     } else { 
      super.commence(request, response, authException); 
     } 
    } 
} 

और यहाँ क्या अपने वसंत संदर्भ एक्सएमएल में चला जाता है है:

<bean id="authenticationEntryPoint" 
    class="com.yoyar.yaya.config.AjaxAwareAuthenticationEntryPoint"> 
    <constructor-arg name="loginUrl" value="/login"/> 
</bean> 

<security:http auto-config="true" 
    use-expressions="true" 
    entry-point-ref="authenticationEntryPoint"> 
    <security:intercept-url pattern="/api/secured/**" access="hasRole('ROLE_USER')"/> 
    <security:intercept-url pattern="/login" access="permitAll"/> 
    <security:intercept-url pattern="/logout" access="permitAll"/> 
    <security:intercept-url pattern="/denied" access="hasRole('ROLE_USER')"/> 
    <security:intercept-url pattern="/" access="permitAll"/> 
    <security:form-login login-page="/login" 
         authentication-failure-url="/loginfailed" 
         default-target-url="/login/success"/> 
    <security:access-denied-handler error-page="/denied"/> 
    <security:logout invalidate-session="true" 
        logout-success-url="/logout/success" 
        logout-url="/logout"/> 
</security:http> 
+0

मैंने इस दृष्टिकोण को लागू किया और मैं टाइमआउट पकड़ता हूं और फिर लॉगिन करने के लिए लॉगिन पेज पर रीडायरेक्ट करता हूं। लॉगिन के बाद मैं AJAX url और क्वेरी स्ट्रिंग को देखता हूं। क्या कोई तरीका है कि मैं उस पेज पर वापस जा सकता हूं जिस पर AJAX अनुरोध शुरू हुआ था? धन्यवाद – blong824

+0

यह एक अच्छा मुद्दा है।यह इस समाधान के लिए वसंत सुरक्षा और ऑर्थोगोनल की एक विशेषता है। हालांकि यह एक समस्या है फिर भी। मैं वर्तमान में एक ही समस्या का सामना कर रहा हूं और इसे हल करने के बाद इस पोस्ट को अपडेट कर दूंगा। अगर आप इस दौरान इसे समझते हैं तो कृपया मुझे बताएं। –

+0

पुन: blong824 की टिप्पणी, यह पृष्ठ निर्देशक है: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/appendix-namespace.html#nsa-form-login। यदि आप पैरामीटर 'हमेशा-उपयोग-डिफ़ॉल्ट-लक्ष्य' को सत्य पर सेट करते हैं तो आप वांछित पृष्ठ पर लॉगिन के बाद सिस्टम को हमेशा रीडायरेक्ट कर सकते हैं। बीन प्रकार से संबंधित समाधानों को भी देखें: 'SimpleUrlAuthenticationSuccessHandler'। मुझे लगता है कि एक अलग पोस्टिंग में अधिक जटिल समाधानों का सबसे अच्छा वर्णन किया गया है। –

8

मैं निम्नलिखित समाधान का इस्तेमाल किया।

वसंत सुरक्षा में अवैध सत्र यूआरएल

<security:session-management invalid-session-url="/invalidate.do"/> 

परिभाषित है कि पेज के लिए निम्नलिखित नियंत्रक जोड़ा

@Controller 
public class InvalidateSession 
{ 
    /** 
    * This url gets invoked when spring security invalidates session (ie timeout). 
    * Specific content indicates ui layer that session has been invalidated and page should be redirected to logout. 
    */ 
    @RequestMapping(value = "invalidate.do", method = RequestMethod.GET) 
    @ResponseBody 
    public String invalidateSession() { 
     return "invalidSession"; 
    } 
} 

और अजाक्स ajaxSetup सभी ajax अनुरोधों को हैंडल करने के लिए इस्तेमाल के लिए:

// Checks, if data indicates that session has been invalidated. 
// If session is invalidated, page is redirected to logout 
    $.ajaxSetup({ 
    complete: function(xhr, status) { 
       if (xhr.responseText == 'invalidSession') { 
        if ($("#colorbox").count > 0) { 
         $("#colorbox").destroy(); 
        } 
        window.location = "logout"; 
       } 
      } 
     }); 
+0

मेरे मामले में, इसके लिए काम करने के लिए मुझे 'अवैध-सत्र = "झूठी" 'to' <सुरक्षा: लॉगआउट लॉगआउट-url = "/ logout" लॉगआउट-सफलता-url = "/ home" /> ', अन्यथा वसंत ने मुझे लॉगआउट बटन पर क्लिक करने के बाद '/ invalidate.do' पर रीडायरेक्ट किया। – matthaeus

+0

क्या यह काम करता है यदि मैं 'expired-url ="/login "' का उपयोग करता हूं? – zygimantus

0

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

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

$(document).ajaxError(function(event, request, settings, exception) { 
    if(String.prototype.indexOf.call(request.responseText, "j_username") != -1) { 
     window.location.reload(document.URL); 
    } 
}); 
0

जब समय समाप्त होता है, उपयोगकर्ता प्रवेश पृष्ठ पर रीडायरेक्ट किया जाता है के बाद किसी भी ajax कार्रवाई करते हुए सत्र पहले से ही

सुरक्षा संदर्भ को मंजूरी दे दी शुरू हो रहा है:

<http use-expressions="true" entry-point-ref="authenticationEntryPoint"> 
    <logout invalidate-session="true" success-handler-ref="logoutSuccessBean" delete-cookies="JSESSIONID" /> 
    <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> 
    <custom-filter position="FORM_LOGIN_FILTER" ref="authFilter" /> 
    <session-management invalid-session-url="/logout.xhtml" session-authentication-strategy-ref="sas"/> 
</http> 

<beans:bean id="concurrencyFilter" 
    class="org.springframework.security.web.session.ConcurrentSessionFilter"> 
    <beans:property name="sessionRegistry" ref="sessionRegistry" /> 
    <beans:property name="expiredUrl" value="/logout.xhtml" /> 
</beans:bean> 

<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> 
    <beans:property name="loginFormUrl" value="/login.xhtml" /> 
</beans:bean> 

<beans:bean id="authFilter" 
    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
    <beans:property name="sessionAuthenticationStrategy" ref="sas" /> 
    <beans:property name="authenticationManager" ref="authenticationManager" /> 
    <beans:property name="authenticationSuccessHandler" ref="authenticationSuccessBean" /> 
    <beans:property name="authenticationFailureHandler" ref="authenticationFailureBean" /> 
</beans:bean> 

<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"> 
    <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" /> 
    <beans:property name="maximumSessions" value="1" /> 
    <beans:property name="exceptionIfMaximumExceeded" value="1" /> 
</beans:bean> 

लॉग इन श्रोता:

public class LoginListener implements PhaseListener { 

@Override 
public PhaseId getPhaseId() { 
    return PhaseId.RESTORE_VIEW; 
} 

@Override 
public void beforePhase(PhaseEvent event) { 
    // do nothing 
} 

@Override 
public void afterPhase(PhaseEvent event) { 
    FacesContext context = event.getFacesContext(); 
    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); 
    String logoutURL = request.getContextPath() + "/logout.xhtml"; 
    String loginURL = request.getContextPath() + "/login.xhtml"; 

    if (logoutURL.equals(request.getRequestURI())) { 
     try { 
      context.getExternalContext().redirect(loginURL); 
     } catch (IOException e) { 
      throw new FacesException(e); 
     } 
    } 
} 

}

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