所以我有一个网络应用程序,它利用jsf和primefaces进行前端演示。
我们使用Spring安全性作为登录机制,并已将并发性定义为
<session-management session-fixation-protection="newSession">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"
expired-url="multipleLogins.xhtml" />
</session-management>
问题似乎是当用户有两次来自不同浏览器的登录时,某些按钮会执行不会触发重定向的ajax操作。它似乎只是提交表单或重定向到页面本身的按钮,它们将识别多个登录操作。
例如,这个按钮
<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}" />
然而,此按钮(当它重定向到另一页时)
任何人都知道如何让webapp将那些ajax调用注册为事件,而不是将所有ajax基于新页面?
答案 0 :(得分:3)
我使用Ben Simpson编写的JSFRedirectStrategy在会话到期时使用会话管理过滤器重定向到会话过期的url。可以找到来源here。 我认为同样可以在这里应用但我们需要删除命名空间配置并添加一些像这样的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;
}
}