2012-08-22 185 views
3

所以我有一個Web應用程序,利用jsf和primefaces進行前端演示。集成彈簧安全與Ajax調用

我們正在使用的登錄機制春天的安全和定義併發這樣

<session-management session-fixation-protection="newSession"> 
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" 
expired-url="multipleLogins.xhtml" /> 
</session-management> 

這個問題似乎是,當用戶有不同的瀏覽器兩個登錄有一些執行Ajax動作一定buttonas那不要觸發重定向。它似乎只是提交表單或重定向到自己的頁面的按鈕,它們將識別多個登錄操作。

例如,這個按鈕

<p:commandButton id="retrieve" value="#{msgs.BUTTON_RETRIEVE}" 
action="#{removeContactForm.retrieve}" update="@form"/> 

從Web服務檢索的東西,並顯示在頁面上,如果有多次登錄不會觸發重定向。

<p:commandButton id="remove" value="#{msgs.BUTTON_REMOVE}" 
action="/pages/confirm/confirmRemove.xhtml" ajax="false" process="@this"   
immediate="true" rendered="#{!empty removeContactManager and 
removeContactManager.contactRolesSuccessful}" /> 

此按鈕但是,(因爲它重定向到另一個頁面)

任何人都知道讓web應用程序註冊這些Ajax調用的事件,而堅持一切辦法基於AJAX到一個新的頁面?

+0

第二個按鈕是否重定向到confirmRemove或multipleLogins? – Ravi

+0

如果有多個登錄,第二個按鈕將正確重定向到'multipleLogins'。第一個不會,因爲它正在初始化一個Ajax調用,而不是去一個新的頁面。 – user898465

回答

3

我使用Ben Simpson編寫的JSFRedirectStrategy在會話過期時使用會話管理過濾器重定向到會話過期URL。來源可以找到here。 我認爲同樣可以應用在這裏,但我們需要刪除的命名空間配置,並添加一些豆類這樣的:

<http> 
    <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> 
    <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter" /> 
    <session-management session-authentication-strategy-ref="sas"/> 
</http> 

<beans:bean id="concurrencyFilter" 
    class="org.springframework.security.web.session.ConcurrentSessionFilter"> 
    <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" /> 
    <beans:constructor-arg name="expiredUrl" value="/multipleLogins.xhtml" /> 
    <!-- this permits redirection to session timeout page from javascript/ajax or http --> 
    <beans:property name="redirectStrategy" ref="jsfRedirectStrategy" /> 
</beans:bean> 

<beans:bean id="myAuthFilter" class= 
    "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
    <beans:property name="sessionAuthenticationStrategy" ref="sas" /> 
    <beans:property name="authenticationManager" ref="authenticationManager" /> 
</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="alwaysCreateSession" value="true" /> 
    <beans:property name="exceptionIfMaximumExceeded" value="true" /> 
</beans:bean> 

<beans:bean id="jsfRedirectStrategy" class="com.examples.JsfRedirectStrategy"/> 
<beans:bean id="sessionRegistry" 
    class="org.springframework.security.core.session.SessionRegistryImpl" /> 

現在,你可以檢查,如果該請求是一個Ajax請求,然後發送重定向這樣在JSFRedirectStrategy類中: 以下是從ICEfaces教程複製的代碼。

/** 
* This class represents an extension to the way DefaultRedirectStrategy works. 
* This class takes into account if the incoming request causing action by Spring Security 
* requires a "partail-response" xml redirect instead of a response.sendRedirect(). 
* 
* @author Ben Simpson [email protected] 
*/ 
public class JsfRedirectStrategy implements RedirectStrategy { 

    protected final Log logger = LogFactory.getLog(getClass()); 

    private boolean contextRelative; 


    /** 
    * Redirects the response to the supplied URL. 
    * <p> 
    * If <tt>contextRelative</tt> is set, the redirect value will be the value after the request context path. Note 
    * that this will result in the loss of protocol information (HTTP or HTTPS), so will cause problems if a 
    * redirect is being performed to change to HTTPS, for example. 
    */ 
    public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { 
     String redirectUrl = calculateRedirectUrl(request.getContextPath(), url); 
     redirectUrl = response.encodeRedirectURL(redirectUrl); 

     if (logger.isDebugEnabled()) { 
      logger.debug("Redirecting to '" + redirectUrl + "'"); 
     } 

     //we should redirect using ajax response if the case warrants 
     boolean ajaxRedirect = request.getHeader("faces-request") != null 
       && request.getHeader("faces-request").toLowerCase().indexOf("ajax") > -1; 

     if(ajaxRedirect) { 
      //javax.faces.context.FacesContext ctxt = javax.faces.context.FacesContext.getCurrentInstance(); 
      //ctxt.getExternalContext().redirect(redirectUrl); 

      String ajaxRedirectXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
       "<partial-response><redirect url=\""+redirectUrl+"\"></redirect></partial-response>"; 
      response.setContentType("text/xml"); 
      response.getWriter().write(ajaxRedirectXml); 
     } else { 
      response.sendRedirect(redirectUrl); 
     } 


    } 

    private String calculateRedirectUrl(String contextPath, String url) { 
     if (!UrlUtils.isAbsoluteUrl(url)) { 
      if (contextRelative) { 
       return url; 
      } else { 
       return contextPath + url; 
      } 
     } 

     // Full URL, including http(s):// 

     if (!contextRelative) { 
      return url; 
     } 

     // Calculate the relative URL from the fully qualified URL, minus the scheme and base context. 
     url = url.substring(url.indexOf("://") + 3); // strip off scheme 
     url = url.substring(url.indexOf(contextPath) + contextPath.length()); 

     if (url.length() > 1 && url.charAt(0) == '/') { 
      url = url.substring(1); 
     } 

     return url; 
    } 

    /** 
    * If <tt>true</tt>, causes any redirection URLs to be calculated minus the protocol 
    * and context path (defaults to <tt>false</tt>). 
    */ 
    public void setContextRelative(boolean useRelativeContext) { 
     this.contextRelative = useRelativeContext; 
    } 
}