คือ เมื่อเกิด session expire แล้วเราทำการส่ง request ที่เป็น ajax กลับไปยัง web server spring security จะปฏิเสธ request นั้นทันที ทำให้ request ไม่เกิดการประมวลผลตาม logic ที่เราเขียนไว้ (request จะนิ่ง ไม่เกิดปฏิกิริยาตอบสนองใดๆ ทั้งสิ้น) ทั้งๆ ที่ตามความเป็นจริงแล้ว มันควรจะเด้งไปที่หน้า login แต่มันก็ไม่ยอมทำ
บทความนี้จะเป็นการแก้ปัญหา ว่าเราจะทำยังไง ให้มันเด้งไปยังหน้า login เมื่อ session expire แล้วได้รับ request ที่เป็น ajax ครับ
แนวคิด
request ที่เป็น ajax ของ jsf นั้น response ที่ถูกส่งกลับมาจะเป็น text/xml รูปแบบประมาณนี้
<?xml version="1.0" encoding="UTF-8"?> <partial-response> .... .... .... </partial-response>ซึ่งข้างใน patial response ก็จะเป็น response ของ logic ที่เราเขียนเอาไว้ ใน managed bean (backing bean หรือ controller)
การทำให้ ajax เกิดการ redirect page ไปยังหน้า login นั้น เราจะต้องทำให้ response ถูกส่งกลับมา แล้วมีรูปแบบดังนี้
<?xml version="1.0" encoding="UTF-8"?> <partial-response> <redirect url="http://your.url.here/"></redirect> </partial-response>คำถาม แล้วเราจะทำยังไงล่ะ ให้มันได้ response แบบนี้?
วิธีการ
1. ที่ applicationContext-security.xml (อ้างอิงจากบทความ การทำ Login ด้วย Spring Security") ให้เพิ่ม xml config ดังต่อไปนี้ลงไป (เราจะ manage session เอง ด้วย session management filter)
.... .... .... <beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter"> <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" /> <beans:property name="invalidSessionStrategy" ref="redirectStrategy"/> </beans:bean> <beans:bean id="redirectStrategy" class="com.blogspot.na5cent.web.security.JsfRedirectStrategy"> <beans:constructor-arg name="invalidSessionUrl" value="/authen/" /> </beans:bean> <beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/> .... .... ....invalidSessionUrl คือ url ที่เราต้องการให้มัน redirect ไป เมื่อ session expire
2. ที่ tag <http/> ให้เพิ่ม custom filter <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER"/> โดยให้ reference ไปยัง config ข้อ 1 ดังนี้
<http use-expressions="true" auto-config="true"> .... .... .... <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER"/> </http>3. จากข้อ 1 มีการประกาศ bean redirectStrategy --> com.blogspot.na5cent.web.security.JsfRedirectStrategy ตัวนี้แหล่ะครับ ที่เราจะต้องไปเขียน code เพื่อให้มัน generate xml redirect ให้เรา ดังนี้
package com.blogspot.na5cent.web.security; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.web.session.InvalidSessionStrategy; import org.springframework.util.StringUtils; /** * Inspired by StackOverflow.com * and by Spring Security 3 and ICEfaces 3 Tutorial. * * @author banterCZ */ public class JsfRedirectStrategy implements InvalidSessionStrategy { private static final Logger LOG = LoggerFactory.getLogger(JsfRedirectStrategy.class); private static final String FACES_REQUEST_HEADER = "faces-request"; private String invalidSessionUrl; public JsfRedirectStrategy(String invalidSessionUrl){ this.invalidSessionUrl = invalidSessionUrl; } /** * {@inheritDoc} */ @Override public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { boolean ajaxRedirect = "partial/ajax".equals(request.getHeader(FACES_REQUEST_HEADER)); if (ajaxRedirect) { String contextPath = request.getContextPath(); String redirectUrl = contextPath + invalidSessionUrl; LOG.debug("Session expired due to ajax request, redirecting to '{}'", redirectUrl); String ajaxRedirectXml = createAjaxRedirectXml(redirectUrl); LOG.debug("Ajax partial response to redirect: {}", ajaxRedirectXml); response.setContentType("text/xml"); response.getWriter().write(ajaxRedirectXml); } else { String requestURI = getRequestUrl(request); LOG.debug("Session expired due to non-ajax request, starting a new session and redirect to requested url '{}'", requestURI); request.getSession(true); response.sendRedirect(requestURI); } } private String getRequestUrl(HttpServletRequest request) { StringBuffer requestURL = request.getRequestURL(); String queryString = request.getQueryString(); if (StringUtils.hasText(queryString)) { requestURL.append("?").append(queryString); } return requestURL.toString(); } private String createAjaxRedirectXml(String redirectUrl) { return new StringBuilder() .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") .append("<partial-response><redirect url=\"") .append(redirectUrl) .append("\"></redirect></partial-response>") .toString(); } public void setInvalidSessionUrl(String invalidSessionUrl) { this.invalidSessionUrl = invalidSessionUrl; } }แค่นี้ก็เป็นอันเสร็จเรียบร้อยครับ
thank you : http://stackoverflow.com/questions/16858017/primefaces-jsf-2-redirect-when-session-expires
ไม่มีความคิดเห็น:
แสดงความคิดเห็น