2012-08-22 152 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; 
    } 
}