Spring security integration with Ajax calls

So, I have a web application that uses jsf and primefaces to represent the front end.

We use Spring Security for the login mechanism and define concurrency as such

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

The problem is that the user has two inputs from different browsers, there are certain buttons that perform ajax actions that do not trigger redirection. It seems that these are only buttons that submit forms or redirect the pages themselves that recognize several login actions.

For example, this button

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

What extracts things from the web service and displays them on the page will not initiate a redirect if there are multiple logins.

<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}" />

However, this button (as it redirects to another page)

- webapp ajax- , ajax ?

+3
1

JSFRedirectStrategy, URL- , . . , , beans :

<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 ben.simpson@icesoft.com
 */
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;
    }
}
+3

All Articles