SUN TEAM & ANYONE!! SecurityFilter Problem

Hi all

i have used and implemented the security filters discussed in

http://forum.java.sun.com/thread.jspa?threadID=5050520

It seems to work fine. If i try to access a page without having logged in first, i get redirected to the login page.

but something very wierd is happening. after logging in, i am 100% sure that the user attribute in session bean is set, since i have a text field that displays it. but if i change anything on the page (drop down selection, dates, etc) or interact with it (bascially any request), the user is redirected to login page.

i dont reset the username in session at any point, so it cant be that the user isnt logged in anymore. and also there was no time out, so that cant be the problem either.

is it a problem with the security filter class? i cant understand what's going on.

the code for the doFilter(...)

method is posted below:

publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException{

HttpServletRequest hreq = (HttpServletRequest)request;

HttpServletResponse hres = (HttpServletResponse)response;

HttpSession session = hreq.getSession();

String url = hreq.getPathTranslated();

boolean notLoginPage = url.endsWith("LiveLogin.jsp") ==false;

boolean isJsp = url.endsWith(".jsp");

/** Dont filter login.jsp because otherwise an endless loop.

* & only filter .jsp otherwise it will filter all images etc as well.

*

*/

if (notLoginPage && isJsp){

/* There is no User attribute so redirect to login page */

if(session.getAttribute("ATTR_USER") ==null){

System.out.println("Session expired, redirecting to login page");

hres.sendRedirect("/SPNLiveBeta3/faces/LiveLogin.jsp");

return;

}

}

/* deliver request to next filter */

chain.doFilter(request, response);

}

}

could anypne please help me find the problem? this is that last step in the development of my application, which should be delivered for testing very soon

MUCH APPRECIATED!!.

[2903 byte] By [InfoSysExpertsa] at [2007-11-26 14:58:01]
# 1

How are you setting the session variable? If it is in SessionBean1 then I believe you need to access it similar to this way:

if ( session != null ) {

com.example.SessionBean1 sb = (com.example.SessionBean1)session.getAttribute("SessionBean1");

if ( sb != null )

String username = sb.getUserName();

}

Keep in mind that you can debug a filter just like any other code. You should be able to set breakpoints and step through the code to see all variables and tell why it is failing.

jsra at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 2
thanks.i'll look into it!
InfoSysExpertsa at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 3

I don't think the Security filter will solve the problem. JSF uses Forward Dispatching instead of redirect. When you send the request to a page this request will hit the filter first. If you try to get the Servelet path and the path info you will find out that these info is about the source page and not about the target page . In order to protect a resource the filter should know where the request is going not where the request is coming form. That is not possible in JSF now unless there is a way to change the default forward dispatch to redirect.

By looking at the JAAS example. the application is trying to protect all resources accept for the login and welcome pages. The filter gets the servlet path and the path info, the path info end with login.jsp then it will allow the access other wise it will check if the user exist in the session or not.

The above solution will work in Struts framework but not in JSF.

Let抯 take a scenario

Form the login page a user enter valid user name and password

The user click on the submit button. The target page is loginSuccess.jsp

The filter intercept the request

The filter extract the servlet path and the path info

Because of the forward dispatching the servlet path and the path inof are belong the source page and in this case longin.jsp, and in this case the path info ends with login.jsp

The filter in this case passes the request without any authenticaion.

This is only one scenario

I don't know how the creator team having the JASS example among the example in the IDE and I don't know how that works.

I might be wrong and the example really work but Filter is not working for me

I think we have only two choices to implements security and session time out in JSF

first one to protect the page indvidually to check if the user in the session this code should go in the prerender() method

second to make all page bean expends custom AbstractBean in witch you write the code for user validation and session time out.

wassimcoa at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 4

> The filter in this case passes the request ...

You are right.

> second to make all page bean expends custom

> AbstractBean in witch you write the code for user

> validation and session time out.

This isn't possible with JSC because it expects page beans directly derived from AbstractPageBean.

I'am using the following solution:

Existing login and permissions are checked in a PhaseListener before RESTORE_VIEW.

All page navigation is done through an action method in backing bean of a page fragment that contains a dynamically generated menu. In this method is checked if the user has permissions for target page. If not send 404.

What I'am missing in JSF is a method based check. So I have to implement a

isActionAllowed(User user, ACTION_TYPE)

in every page bean and call this method first in every action method

public String button...ACTION_TYPE_action()

{

if (! isActionAllowed(ACTION_TYPE)

{

return null;

}

}

Any better ideas?

I don't want to check the request for parameters like "form1_hidden" and "form1:tabSet1:layoutPanel1:...:...:...:buttonSomeAction" because this depends on the JSF implementation. (Or is this a part of the specification?)

Ingmara at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 5

There is nothing wrong with Extending a CustomAbstractpageBean , and it should work. I had this code in a hurry and it might need some work and the only purpose of this code is to demonstrate the idea.

/*

* CustomAbstractpageBean.java

*

* Created on February 28, 2007, 9:13 AM

*

* To change this template, choose Tools | Options and locate the template under

* the Source Creation and Management node. Right-click the template and choose

* Open. You can then make changes to the template in the Source Editor.

*/

package estimate;

import com.sun.rave.web.ui.appbase.AbstractPageBean;

import javax.servlet.RequestDispatcher;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/*

* CustomAbstractpageBean.java

*

* Created on February 28, 2007, 9:08 AM

*

* To change this template, choose Tools | Options and locate the template under

* the Source Creation and Management node. Right-click the template and choose

* Open. You can then make changes to the template in the Source Editor.

*/

/**

*

* @author wzahra

*/

public abstract class CustomAbstractpageBean extends AbstractPageBean{

/** Creates a new instance of CustomAbstractpageBean */

public CustomAbstractpageBean() {

}

public void init() {

// Perform initializations inherited from our superclass

super.init();

// Perform application initialization that must complete

// *before* managed components are initialized

// TODO - add your own initialiation code here

// <editor-fold defaultstate="collapsed" desc="Creator-managed Component Initialization">

// Initialize automatically managed components

// *Note* - this logic should NOT be modified

// </editor-fold>

// Perform application initialization that must complete

// *after* managed components are initialized

// TODO - add your own initialization code here

int i=0;

}

/**

*

Callback method that is called after the component tree has been

* restored, but before any event processing takes place. This method

* will <strong>only</strong> be called on a postback request that

* is processing a form submit. Customize this method to allocate

* resources that will be required in your event handlers.

*/

protected RequestBean1 getRequestBean1() {

return (RequestBean1)getBean("RequestBean1");

}

/**

*

Return a reference to the scoped data bean.

*/

protected ApplicationBean1 getApplicationBean1() {

return (ApplicationBean1)getBean("ApplicationBean1");

}

/**

*

Return a reference to the scoped data bean.

*/

protected SessionBean1 getSessionBean1() {

return (SessionBean1)getBean("SessionBean1");

}

/**

*

Callback method that is called just before rendering takes place.

* This method will <strong>only</strong> be called for the page that

* will actually be rendered (and not, for example, on a page that

* handled a postback and then navigated to a different page). Customize

* this method to allocate resources that will be required for rendering

* this page.

*/

public void prerender() {

/**Code for Authentication and session Timeout can be placed here..........*/

String userId= this.getSessionBean1().getUserId();

String activeSession=this.getSessionBean1().getActiveSession();

if(userId==null|| activeSession==null) {

HttpServletRequest req=(HttpServletRequest)this.getFacesContext().getExternalContext().getRequest();

HttpServletResponse res=(HttpServletResponse)this.getFacesContext().getExternalContext().getResponse();

RequestDispatcher dispatcher=req.getRequestDispatcher("/faces/Login.jsp");

try{

dispatcher.forward(req, res);

} catch(Exception e) {

error("Can not forword to Login page");

}

}

}

/**

*

Callback method that is called after rendering is completed for

* this request, if <code>init()</code> was called (regardless of whether

* or not this was the page that was actually rendered). Customize this

* method to release resources acquired in the <code>init()</code>,

* <code>preprocess()</code>, or <code>prerender()</code> methods (or

* acquired during execution of an event handler).

*/

}

and in your pageBean.....some attension to the extends cluase and prerender() method.

public class Page1 extends CustomAbstractpageBean{

// <editor-fold defaultstate="collapsed" desc="Creator-managed Component Definition">

private int __placeholder;

/**

*

Automatically managed component initialization. <strong>WARNING:</strong>

* This method is automatically generated, so any user-specified code inserted

* here is subject to being replaced.

*/

private void _init() throws Exception {

}

private Page page1 = new Page();

public Page getPage1() {

return page1;

}

public void setPage1(Page p) {

this.page1 = p;

}

/**

*

Construct a new Page bean instance.

*/

public Page1() {

}

/**

*

Return a reference to the scoped data bean.

*/

protected RequestBean1 getRequestBean1() {

return (RequestBean1)getBean("RequestBean1");

}

/**

*

Return a reference to the scoped data bean.

*/

protected ApplicationBean1 getApplicationBean1() {

return (ApplicationBean1)getBean("ApplicationBean1");

}

/**

*

Return a reference to the scoped data bean.

*/

protected SessionBean1 getSessionBean1() {

return (SessionBean1)getBean("SessionBean1");

}

/**

*

Callback method that is called whenever a page is navigated to,

* either directly via a URL, or indirectly via page navigation.

* Customize this method to acquire resources that will be needed

* for event handlers and lifecycle methods, whether or not this

* page is performing post back processing.

*

*

Note that, if the current request is a postback, the property

* values of the components do <strong>not</strong> represent any

* values submitted with this request. Instead, they represent the

* property values that were saved for this view when it was rendered.

*/

public void init() {

// Perform initializations inherited from our superclass

super.init();

// Perform application initialization that must complete

// *before* managed components are initialized

// TODO - add your own initialiation code here

// <editor-fold defaultstate="collapsed" desc="Creator-managed Component Initialization">

// Initialize automatically managed components

// *Note* - this logic should NOT be modified

try {

_init();

} catch (Exception e) {

log("Page1 Initialization Failure", e);

throw e instanceof FacesException ? (FacesException) e: new FacesException(e);

}

// </editor-fold>

// Perform application initialization that must complete

// *after* managed components are initialized

// TODO - add your own initialization code here

int i=0;

}

/**

*

Callback method that is called after the component tree has been

* restored, but before any event processing takes place. This method

* will <strong>only</strong> be called on a postback request that

* is processing a form submit. Customize this method to allocate

* resources that will be required in your event handlers.

*/

public void preprocess() {

}

/**

*

Callback method that is called just before rendering takes place.

* This method will <strong>only</strong> be called for the page that

* will actually be rendered (and not, for example, on a page that

* handled a postback and then navigated to a different page). Customize

* this method to allocate resources that will be required for rendering

* this page.

*/

public void prerender() {

super.prerender();

int i=0;

}

/**

*

Callback method that is called after rendering is completed for

* this request, if <code>init()</code> was called (regardless of whether

* or not this was the page that was actually rendered). Customize this

* method to release resources acquired in the <code>init()</code>,

* <code>preprocess()</code>, or <code>prerender()</code> methods (or

* acquired during execution of an event handler).

*/

public void destroy() {

}

public String button1_action() {

// TODO: Process the button click action. Return value is a navigation

// case name where null will return to the same page.

int i=0;

return "case1";

}

wassimcoa at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 6
Have you tried to create a new PageBean by extending your CustumAbstractPageBean using JSC?
Ingmara at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 7
The design view of JSC has some restrictions. One of them is the fact, that page beans have to extend AbstractPageBean. It's possible, that this behaviour has changed in the last few months. I didn't check it.
Ingmara at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 8
http://forum.java.sun.com/thread.jspa?threadID=5128292
Ingmara at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...
# 9

You are right we can not extend AbstractBean. This will effect the design view so we will be having problem in Design time.

We left with only one choice which is to include the code in the prender method

Or

We can extends the AbstractBean once we finish designing the app and we want to deploy it. I know this is not a good solution but I am trying to find a work around to this problem

there is one more thing that we can try as well and that in navigation.xml we include <redirect/> tag to switch from forward Dispatching to redirect dispatching..

<navigation-case>

<from-outcome>Home</from-outcome>

<to-view-id>/Home.jsp</to-view-id>

</navigation-case>

then try to use that with servlet Filter. make sure to bypass any url that does not end with .jsp... I will continue working on this problem and I hope we can get some help form the creator Team because I see this issue very important and I don't think we can implement good security without filter and more specifically Filter is the standard implementation for interceptor in Servert 2.0 so Creator should be able to implement some kind of interceptor.

wassimcoa at 2007-7-8 8:46:49 > top of Java-index,Development Tools,Java Tools...