我使用了 Ben Simpson 编写的 JSFRedirectStrategy 在会话过期时使用会话管理过滤器重定向到会话过期 url。来源可以在这里找到。我认为同样可以在这里应用,但我们需要删除命名空间配置并添加一些像这样的 bean:
<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;
}
}