Tuesday, February 2, 2010

JDeveloper, Weblogic and ADF: Security in Oracle ADF and Session invalidate

In enterprise applications that require user authentication, a user can't navigate back to a cached page. When developing applications using JDeveloper11g ADF, I encountered two problems.

First, how to kill a user session when clicking logout button, as explained below:
In ADF, you might use SessionScope to create variables or beans that can be carried out during the life cycle of a user session. Destroying the session bean or setting a session variable to null doesn't mean that the session is killed, to kill a session you have to:

1- Add a method call to logout button Action can be in the managed or backing bean and name it logout_action();

2- The code is used to invalidate the user session then redirect the page to your login screen displayed below:

        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ectx = fc.getExternalContext();      
        HttpSession session = (HttpSession)ectx.getSession(false);
        try {
            session.invalidate();          
            ectx.redirect("../loginpage");
            fc.responseComplete();
        } catch (Exception exp) {
            ectx.redirect("../loginpage");
            fc.responseComplete();
        }

* note if you are using a bounded task flow and your loging screen exists in unbounded task flow located one level up then consider navigating through floders using (..) till login screen location.



Second, how to prevent accessing a cached page that contains data retrieved using a Java method call and filled out in PageFlowScope or ViewScope variables, and then written through expression language to page (like building an old JSP page), without accessing any business component directly through drag and drop.

The first to do is to prevent IE from caching the pages by setting the response headers to no-cache, no-store and must re-validate through setting a listener at faces-config.xml file, that will execute before page being validated and sent to client browser:

public class CachControlListener implements PhaseListener {
public CachControlListener() {
super(); }

public PhaseId getPhaseId() { return PhaseId.RENDER_RESPONSE; }

public void afterPhase(PhaseEvent event) {
}

public void beforePhase(PhaseEvent event) {
FacesContext facesContext = event.getFacesContext();

HttpServletResponse response =
(HttpServletResponse)facesContext.getExternalContext().getResponse(); response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Control", "no-cache");

response.addHeader("Cache-Control", "no-store");

response.addHeader("Cache-Control", "must-revalidate");
response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");}
}





This will work fine with Internet Exporlor. But, a problem may appear with firefox that it ignores page headers directives, which require farther additions by disabling the back button. To do that you need to redirect the client forward in history, this done by using history.go(+1); added under the view tag in the main jspx page:

5 comments:

  1. in session invalidate
    after response.sendRedirect
    we must write ctx.responseComplete();
    otherwise
    an illegalstateException may appear

    ReplyDelete
  2. I chanced upon to view your blog and found it very interesting. Great ... Keep it up!
    application development

    ReplyDelete
  3. Thanks appreciate your comments.
    I modified the post eariler to avoid throwing an exception.

    ReplyDelete
  4. hi ,
    its redirecting to the page ,but its throwing some exception while redirecting.

    oracle.adf.controller.internal.InvalidViewPortIdException: ADFC-14000: View port ID 'vhne2x4vo_0' is invalid.

    ReplyDelete
  5. How to invalidate the session and close the browser window/tab too in this case ?

    ReplyDelete