세션 타임아웃 및 View ExpiredJSF/PrimeFaces ajax 요청에 대한 예외 처리
이 문서는 세션 만료 및 ViewExpired 처리 방법 비 ajax 요청에 유용합니다.JSF 2에서는 예외입니까?하지만 AJAX 콜을 사용하여 송신할 때는 이 기능을 사용할 수 없습니다.
prime faces 대화상자에서 AJAX를 사용하여 포스트 요청을 하고 있는데 세션이 이미 타임아웃되었다고 가정합니다.내 페이지가 막히네요.
어떻게 하면 AJAX를 사용하여 게시할 때 그를 내 View expired 페이지로 리다이렉트하고 위의 링크의 솔루션과 같은 로그인 페이지로 전송할 수 있을까요?
JSF2/프라임페이스/글라스피쉬
Ajax 요청 중에 발생하는 예외는 기본적으로 클라이언트 측에 피드백이 전혀 없습니다.로 설정되어 있는 를 실행합니다.Development
를 사용합니다.<f:ajax>
자바스크립트Prime Faces 。그러나 서버 로그와 Ajax 응답(웹 브라우저 개발자 도구 집합의 "네트워크" 섹션)에서 예외를 볼 수 있습니다.
기본적으로 다음과 같은 작업을 수행하는 커스텀을 구현해야 합니다.ViewExpiredException
: 큐 내:
String errorPageLocation = "/WEB-INF/errorpages/expired.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();
또는 JSF 유틸리티 라이브러리 OmniFaces 를 사용할 수도 있습니다.바로 이 목적을 위한 것이 있습니다(소스 코드는 이쪽, 쇼케이스 데모는 이쪽).
다음 항목도 참조하십시오.
- <error-page> 리다이렉트 대신 JSF Exception Handler Factory를 사용하는 이유는 무엇입니까?
- AJAXified 구성 요소에 대한 JSF 2.0 예외를 처리하는 올바른 방법은 무엇입니까?
@BalusC의 답변과 이 투고를 합쳐서 고민을 해결했습니다!
My Exception Handler Wrapper:
public class CustomExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
CustomExceptionHandler(ExceptionHandler exception) {
this.wrapped = exception;
}
@Override
public ExceptionHandler getWrapped() {
return wrapped;
}
@Override
public void handle() throws FacesException {
final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
while (i.hasNext()) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context
= (ExceptionQueuedEventContext) event.getSource();
// get the exception from context
Throwable t = context.getException();
final FacesContext fc = FacesContext.getCurrentInstance();
final Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
final NavigationHandler nav = fc.getApplication().getNavigationHandler();
//here you do what ever you want with exception
try {
//log error ?
//log.log(Level.SEVERE, "Critical Exception!", t);
if (t instanceof ViewExpiredException) {
requestMap.put("javax.servlet.error.message", "Session expired, try again!");
String errorPageLocation = "/erro.xhtml";
fc.setViewRoot(fc.getApplication().getViewHandler().createView(fc, errorPageLocation));
fc.getPartialViewContext().setRenderAll(true);
fc.renderResponse();
} else {
//redirect error page
requestMap.put("javax.servlet.error.message", t.getMessage());
nav.handleNavigation(fc, null, "/erro.xhtml");
}
fc.renderResponse();
// remove the comment below if you want to report the error in a jsf error message
//JsfUtil.addErrorMessage(t.getMessage());
} finally {
//remove it from queue
i.remove();
}
}
//parent hanle
getWrapped().handle();
}
}
My Exception Handler Factory:
public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory parent;
// this injection handles jsf
public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler handler = new CustomExceptionHandler(parent.getExceptionHandler());
return handler;
}
}
my faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<factory>
<exception-handler-factory>
your.package.here.CustomExceptionHandlerFactory
</exception-handler-factory>
</factory>
</faces-config>
JBoss 7에서 Mojarra 2.1.7을 프로덕션 모드로 사용하고 있습니다.세션이 만료된 후 AJAX 호출은 오류 XML 문서를 반환합니다.f:ajax의 일반적인 onerror 핸들러를 사용하면 이 오류를 쉽게 발견할 수 있습니다.
<script type="text/javascript">
function showError(data) {
alert("An error happened");
console.log(data);
}
</script>
<h:commandLink action="...">
<f:ajax execute="..." render="..." onerror="showError"/>
</h:commandLink>
이것을 View Expired에 포함시켰습니다.Exception Handler 클래스로 WAS에서 잘 작동했습니다.
public void handle() throws FacesException {
FacesContext facesContext = FacesContext.getCurrentInstance();
for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents()
.iterator(); iter.hasNext();) {
Throwable exception = iter.next().getContext().getException();
if (exception instanceof ViewExpiredException) {
final ExternalContext externalContext = facesContext
.getExternalContext();
try {
facesContext.setViewRoot(facesContext.getApplication()
.getViewHandler()
.createView(facesContext, "/Login.xhtml")); //Login.xhtml is the page to to be viewed. Better not to give /WEB-INF/Login.xhtml
externalContext.redirect("ibm_security_logout?logoutExitPage=/Login.xhtml"); // when browser back button is pressed after session timeout, I used this.
facesContext.getPartialViewContext().setRenderAll(true);
facesContext.renderResponse();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
iter.remove();
}
}
}
getWrapped().handle();
}
도움이 되었으면 좋겠다
세션 타임아웃 후 사용자가 작업을 수행할 때 Requirement에 확인 팝업이 표시되어야 한다는 문제에 직면했습니다.제안된 해결책은 다음과 같습니다.
<security:http use-expressions="true" auto-config="true" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/common/auth/**" access="permitAll" />
<security:intercept-url pattern="/javax.faces.resource/**" access="permitAll" />
<security:intercept-url pattern="/**/ *.*" access="hasRole('ROLE_ADMIN')" />
<security:form-login login-page="/common/auth/login.jsf" />
<!-- <security:remember-me key="secret" services-ref="rememberMeServices" /> -->
<security:logout invalidate-session="true" logout-success-url="/common/auth/login.jsf" />
</security:http>
<bean id="authenticationEntryPoint" class="com.x.y.MyRedirectEntryPoint" >
<property name="loginFormUrl" value="/common/auth/login.jsf"/>
</bean>
MyRedirectEntryPoint는 Authentication Processing FilterEntryPoint를 확장하고 시작 메서드를 덮어씁니다.
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
boolean ajaxRedirect = request.getHeader("faces-request") != null
&& request.getHeader("faces-request").toLowerCase().indexOf("ajax") > -1;
if (ajaxRedirect) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
response.sendError(403);
}
} else {
super.commence(request, response, authException);
}
}
이제 콜백 javascript 함수를 바인딩하여 던져진 403 오류를 포착하고 원하는 작업을 수행할 수 있습니다.
$(document).bind('ajaxError',
function(event, request, settings, exception){
if (request.status==403){
//do whatever you wanted may be show a popup or just redirect
window.location = '#{request.contextPath}/';
}
});
저는 단순한 클라이언트 측 Javascript 핸들러가 작동했습니다.
function handleAjaxExpired(xhr,status,args) {
// handler for "oncomplete" ajax callback
if ( xhr.responseXML.getElementsByTagName('error-name').length ) {
// "<error-name>" tag is present -> check for "view expired" exception
html = xhr.responseXML.getElementsByTagName('error-name')[0].innerHTML;
if ( html.indexOf('ViewExpiredException') > -1 ) {
// view expired exception thrown
// do something / reload page
if ( confirm('session expired -> reload page?') ) {
document.location.href=document.location.href;
}
}
}
}
이 핸들러는 UI 요소를 트리거할 때 "oncomplete" 속성에서 호출됩니다. 예를 들어 Primefaces 데이터 테이블의 rowSelect 이벤트에서 호출됩니다.
<p:ajax event="rowSelect" oncomplete="handleAjaxExpired(xhr,status,args)" />
업데이트: 모든 Ajax 지원 요소에 "oncomplete" 속성이 추가되는 것을 방지하기 위해 이 Javascript 코드는 모든 Ajax 응답에서 글로벌하게 오류를 검색합니다.
(function() {
// intercept all ajax requests
var origXHROpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
this.addEventListener('load', function() {
handleAjaxExpired(this);
});
origXHROpen.apply(this, arguments);
};
})();
이 코드로 인해 PrimeFaces UI 요소의 "oncomplete" 속성이 사용되지 않게 됩니다.
언급URL : https://stackoverflow.com/questions/11203195/session-timeout-and-viewexpiredexception-handling-on-jsf-primefaces-ajax-request
'programing' 카테고리의 다른 글
Wordpress에서 페이지 제목을 가져오는 방법 (0) | 2023.03.02 |
---|---|
메이븐 + 스프링 부트:org.json이 여러 개 발견되었습니다.클래스 경로의 JSONObject: (0) | 2023.03.02 |
Json.net의 늘필드 무시 (0) | 2023.03.02 |
React Hook useEffect에 종속성이 누락되었습니다. '리스트' (0) | 2023.03.02 |
REST API를 사용하여 게시할 사용자 지정 분류법 할당 (0) | 2023.03.02 |