Solved

Intercepting j_security_check in Websphere 7

Posted on 2012-04-12
17
4,315 Views
Last Modified: 2012-08-13
Hello. I am trying to do some modifications to the authentication workflow. I have a login.jsp on Websphere 7 whereby I call j_security_check to authenticate with Active Directory. Due to some complex requirements, I need to process the j_username and j_password variables before performing j_security_check.

Although it was said that pre-login processing cannot be done, the asker was using Tomcat and not Websphere. I found that there is a solution for my problem over here but it seems that everytime I try to login, I receive a "The website cannot display the page. The website has a programming error."

I tried troubleshooting by checking if the syntax was correct. Found some inconsistencies and corrected them as best I could. However, I still keep getting the same error.

My LoginFilter.java in /WEB-INF/classes/ has only 3 functions:
public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
     }

public void destroy() {
        this.filterConfig = null;
     }

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
         // perform pre-login action here
         chain.doFilter(request, response);  
         }

Open in new window

My filter edit for web.xml in /WEB-INF/
<filter id="Filter_1">
    <filter-name>LoginFilter</filter-name>
    <filter-class>LoginFilter</filter-class>
    <description>Performs pre-login operation</description>
</filter>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/j_security_check</url-pattern>
</filter-mapping>

Open in new window

Could someone throw me in the right direction? My <url-pattern> is /protected/* and I have my <transport-guarantee> as CONFIDENTIAL with the file listing of:
/welcome.jsp
/login.jsp
/protected/index.jsp
/web-inf/web.xml
/web-inf/classes/LoginFilter.java

Thank you.
0
Comment
Question by:pcssecure
  • 9
  • 8
17 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 37841117
Some troubleshooting steps...


If you simply remove the filter from web.xml, does the error you are getting go away? (I realise the app might not work as it should, I am just trying to narrow down what is happening)

Is that truly what code you have for your LoginFilter at the moment, ie. a filter that does nothing, or have you just removed the processing code to post it here?

Can you put a breakpoint/log message in your doFilter method to see if it is getting called?
0
 

Author Comment

by:pcssecure
ID: 37841222
Hi,

Yes. Upon removal of the <filter> and <filter-mapping>, the program works as per normal. Also, I have removed the processing codes just to post it here. It is basically a .js that encrypts text on the client side and sends it over, while on the server side, there is a .java to decrypt the text and pass it onto j_security_check.

I tried to put in a System.out.println("Status:"); but I get the Programming Error before I could see anything.
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37841238
Try your filter without the processing, just to try and narrow down further where the issue is, ie. pretty much as you posted above.

Also, have you tried poking around in the Websphere logs for something that may be more useful to troubleshoot, ie. stack traces, etc?
0
 

Author Comment

by:pcssecure
ID: 37841398
Hi. Yes, I checked it out under Runtime Events:
SRVE0232E: Internal Server Error. <br> Exception Message: [javax.servlet.ServletException: Filter [LoginFilter]: Could not find required filter class - LoginFilter.class at com.ibm.ws.webcontainer.filter.WebAppFilterManager._loadFilter(WebAppFilterManager.java:511) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.loadFilter(WebAppFilterManager.java:462) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.getFilterInstanceWrapper(WebAppFilterManager.java:319) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.getFilterChain(WebAppFilterManager.java:379) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:860) at ... ... ...
Message type: Runtime error
Message originator: com.ibm.ws.webcontainer

I suspect that it couldn't access the filter but I followed the help document to the letter. As such, I've not a clue as to where to begin troubleshooting...
0
 
LVL 35

Assisted Solution

by:mccarl
mccarl earned 500 total points
ID: 37841417
Ah yes, now I see what is happening...

> My LoginFilter.java in /WEB-INF/classes/

You need to COMPILE your filter, just the source .java file is not enough. Compile it to a LoginFilter.class file and then put THAT in your /WEB-INF/classes/ folder!
0
 

Author Comment

by:pcssecure
ID: 37841500
OH CHRIST! I was blind to overlook the error LoginFilter.class... Ha. I'll try that...
0
 

Author Comment

by:pcssecure
ID: 37850236
Hi mccarl,

I compiled it into a LoginFilter.class with servlet-api-2.3.jar and loaded it into my WebSphere. There is no more error. However, even after I put in some test processing, it doesn't seem to work.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
    HttpServletResponse res = (HttpServletResponse)response;
    HttpServletRequest req = (HttpServletRequest)request;
    String username = req.getParameter("j_username");
    if (username == "admin")
    {
        req.setAttribute("j_username", "administrator");
    }	 
    chain.doFilter(req, res);
}

Open in new window

I just wanted to test and see if I am able to replace the j_username variable before sending it to j_security_check. My userid/password pair is administrator/password and I wanted to see if this filter could autocomplete admin to administrator.

Unfortunately, it still does not work. I'm not even sure whether the filter was called or not because I cannot do any modifications to the values. "System.out.println("Test");" does not work as well. Tried to do some modifications by modifying the response and request variables directly.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
    String username = request.getParameter("j_username");
    if (username == "admin")
    {
        req.setAttribute("j_username", "administrator");
    }	 
    chain.doFilter(request, response);
}

Open in new window

I thought it might be the response section, but res.setAttribute or response.setAttribute would create an error when compiling to a .class file. Am I doing something wrong here?
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37854100
Not sure why your System.out.println() isn't working, you may have to investigate that further. Note that websphere may be capturing that somewhere in a log file that you haven't noticed!?

As for what you are really trying to do... You can't do it like that. Firstly, "attributes" and totally different to "parameters". You need to modify the parameter that comes in, however the ServletRequest interface has no facility for "setting parameters". What you need to do is to "wrap" the original request with a customised version of HttpServletRequestWrapper, in which you override the getParameter() method to return "administrator" when the original request's getParameter() returns "admin". Then you pass this wrapped request object to the chain.doFilter() method instead of the original one.

For example,
public class MyHttpServletRequest extends HttpServletRequestWrapper {
  @Override
  public String getParameter(String name) {
    if ("j_username".equals(name) && "admin".equals(getRequest().getParameter("name"))) {
      return "administrator";
    }
  return super.getParameter(name);
  }
}

Open in new window

and then your doFilter method would look like...
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
    chain.doFilter(new MyHttpServletRequest(request), response);
}

Open in new window

0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:pcssecure
ID: 37854878
Thanks for your help.

I'm moving towards HttpServletRequestWrapper to solve this problem. Am trying to get it to compile first using servlet-api-2.3.jar and servlet-api-2.5.jar but I keep getting a few errors. For one, putting them into the same .java file to compile will result in a "MyHttpServletRequest is public, shoudl be declared in a file named MyHttpServletRequest.java". Another would be a "cannot find symbol : constructor HttpServletRequestWrapper()".

I checked out some examples from here but it doesn't seem to explain much.
0
 
LVL 35

Assisted Solution

by:mccarl
mccarl earned 500 total points
ID: 37855677
If you want it in the same file, put the MyHttpServletRequest  class inside your Filter class, (and make the declaration as "public static class MyHttpServletRequest extends HttpServletRequestWrapper").

And yeah, sorry you will need a constructor for MyHttpServletRequest as well, such as ...

public MyHttpServletRequest(HttpServletRequest request) {
  super(request);
}

Open in new window


If it is still not happy, post your entire .java file and we can fix it from there.
0
 

Author Comment

by:pcssecure
ID: 37859989
Hi mccarl,

Here is my code for MyLoginFilter.java
package com.myloginfilter;

import javax.servlet.*;
import javax.servlet.http.*;

public class MyLoginFilter implements Filter {

    protected FilterConfig filterConfig;

    public void init(FilterConfig filterConfig) throws ServletException {
       this.filterConfig = filterConfig;
    }

    public void destroy() {
       this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
		chain.doFilter(new MyRequestWrapper(request), response);
    }

}

Open in new window

And here is my code for MyRequestWrapper.java
package com.myloginfilter;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyRequestWrapper extends HttpServletRequestWrapper {
    
	public MyRequestWrapper(HttpServletRequest request) {
		super(request);
	}
	
	@Override
    public String getParameter(String name) {

		if ("j_username".equals(name) && "admin".equals(getRequest().getParameter("name"))) {
		return "administrator";
		}
		return super.getParameter(name);
	}
}

Open in new window


The above mentioned is as per your suggestion.

Under cmd.exe, I went to my JDK 1.6 folder and entered:
"javac -cp servlet-api-2.5.jar MyRequestWrapper.java" <--- successful
"javac -cp servlet-api-2.5.jar MyLoginFilter.java" <--- unsuccessful
I also tried "javac -cp servlet-api-2.5.jar *.java" but I get the same error.
Error is "cannot find symbol - class MyRequestWrapper"
Error @ "chain.doFilter(new MyRequestWrapper(request), response);"

Meanwhile, I will try the sample on IBM and also this other sample that I found.
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37860511
Easiest way is to probably just put it all in one file, so try the below...

package com.myloginfilter;

import javax.servlet.*;
import javax.servlet.http.*;

public class MyLoginFilter implements Filter {

    protected FilterConfig filterConfig;

    public void init(FilterConfig filterConfig) throws ServletException {
       this.filterConfig = filterConfig;
    }

    public void destroy() {
       this.filterConfig = null;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {
		chain.doFilter(new MyRequestWrapper((HttpServletRequest) request), response);
    }

public static class MyRequestWrapper extends HttpServletRequestWrapper {
    
	public MyRequestWrapper(HttpServletRequest request) {
		super(request);
	}
	
	@Override
    public String getParameter(String name) {

		if ("j_username".equals(name) && "admin".equals(getRequest().getParameter("name"))) {
		return "administrator";
		}
		return super.getParameter(name);
	}
}
}

Open in new window

0
 

Author Comment

by:pcssecure
ID: 37860714
Hi mccarl,

Thank you. I managed to get it compiled. I try to modify it a bit, is this method possible?
public String getParameter(String name) {
    String username = getRequest().getParameter("name")
    if ("j_username".equals(name) && "admin".equals(username))) {;
        username = "administrator";
        // username = clientProvidedFunction(username);
        return username;
    }
        return super.getParameter(name);
    }
}

Open in new window

The reason for converting it into a string of "username" is so that I can perform some modifications to the value by calling a function provided by the client. I noticed there were 2 files inside as well:
MyLoginFilter.class
MyLoginFilter$MyRequestWrapper.class


Does this mean I have to put both .class files into the \WEB-INF\classes\ folder and also modify my web.xml with:
<filter id="Filter_1">
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.myloginfilter</filter-class>
    <description>Performs pre-login operation</description>
</filter>
0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
ID: 37863652
A couple of things here..

1. Yeah, the way that you have changed it looks fine. One thing though, is the "clientProvidedFunction" provided in a .jar, or .class, or as just source code, ie. a .java? It may affect how you now have to compile your code.

2. I stuffed up a little in what I posted, in that I asked for the wrong parameter from the request. So line 2 above should be...
String username = getRequest().getParameter("j_username");

Open in new window


3. Yes, both class files need to be present, but since you have your class in a package now, you need to put the class files in the correct directory, which would be \WEB-INF\classes\com\myloginfilter\

4. In your web.xml you need to give the fully qualified class name, which means the package name AND the class name, so your filter-class element should be...
<filter-class>com.myloginfilter.MyLoginFilter</filter-class>

Open in new window



Hope all that helps get you closer!
0
 

Author Comment

by:pcssecure
ID: 37864041
Hi mccarl,

Thank you for your help.

It works and I feel I got a little more educated at this. Haha!

Shall try to implement my client's filter and if I meet into problem, that'll be another question for another time.

Cheers!
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37864048
No worries, glad to be of assistance!
0
 

Author Comment

by:pcssecure
ID: 37895428
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
ArrayLists in ArrayLists/HashMaps? 4 40
DNS, website, godaddy 6 43
spamming  on Hosted svrs? 6 49
github account with ecipse 1 17
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now