将Spring Security与Ajax调用集成 [英] Integrating spring security with Ajax calls

查看:99
本文介绍了将Spring Security与Ajax调用集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有一个使用jsf和primefaces作为其前端演示文稿的Web应用程序.

So I have a web app that utilises jsf and primefaces for it's front end presentation.

我们将Spring安全性用于登录机制,并已将并发性定义为这样

We are using Spring security for the login mechanism and have defined the 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>

问题似乎是当用户从不同的浏览器进行两次登录时,某些按钮会执行不触发重定向的Ajax操作.似乎只有提交表单或重定向到页面的按钮本身可以识别多种登录操作.

The problem seems to be when a user has two logins from different browsers there are certain buttonas that perform ajax actions that do not trigger the redirect. It seems to only be buttons that submit forms or redirect to pages themselves that will recognise the multiple logins actions.

例如,此按钮

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

从多个Web服务中检索内容并将其显示在页面上,如果有多个登录名,则不会触发重定向.

Which retrieves things from a web service and displays them on a page will not trigger the 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}" />

但是此按钮将(在重定向到另一页时显示)

This button will however (as it redirects to another page)

任何人都知道一种使webapp将那些ajax调用注册为事件的方法,而不会将所有基于ajax的内容都粘贴到新页面中吗?

Anyone know a way of making the webapp register those ajax calls as events, without sticking everything ajax based into a new page?

推荐答案

我使用Ben Simpson编写的JSFRedirectStrategy,用于在使用会话管理过滤器的会话过期时重定向到会话过期的url.可以在此处找到来源. 我认为同样可以在这里应用,但是我们需要删除名称空间配置,并添加一些像这样的bean:

I have used the JSFRedirectStrategy written by Ben Simpson for redirecting to a session expired url when the session expires using the session management filter. Source can be found here. I think the same can be applied here but we need to remove the namespace configuration and add some beans like this:

<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教程复制的代码.

Now, you can check if the request was an ajax request and then send a redirect like this in the JSFRedirectStrategy class: Here is the code copied from the ICEfaces tutorial.

/**
 * 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;
    }
}

这篇关于将Spring Security与Ajax调用集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆