login page automatically redirects to else case - validation

this code shud check login credentials and forward either to logged in page for admin when getParameter(7)=1 or to customer when it is 0..
if login credentials are not correct it will go to error messages and fromt her to login page again.. but somehow it is directly going to errorpage in else case if its not admin!! next two cases are not being checked at all!!
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mutualfund", "root", "");
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT * FROM login_table;");
String uname= request.getParameter("username");
String pass= request.getParameter("password");
while(result.next())
{
if(result.getString(1).equals(uname) && result.getString(2).equals(pass))
{
if(result.getBoolean(7)==true)
{
response.sendRedirect("displayFunds.jsp");
}
if((result.getBoolean(7)==false) && (result.getString(4).equals("")))
{
response.sendRedirect("changePassword.jsp?name="+uname+"&&pass="+pass);
}
if((result.getBoolean(7)==false) && (!result.getString(4).equals("")))
{
response.sendRedirect("custProfile.jsp");
}
}
else
{
response.sendRedirect("loginFailed.jsp");
}
}
}
catch (Exception ex) {
Logger.getLogger(Admin.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

You're not returning from the method, but continuing to iterate through the while loop. You seem to expect that a simple method call response.sendRedirect() magically aborts the whole while loop and returns from the method. It doesn't do that. The code just continues the loop, checking the next user and setting the redirect URL, hereby overriding the previous one.
You need to return from the method yourself.
response.sendRedirect(someURL);
return;
Your concrete problem is caused because your login doesn't match the last user entry in the DB.
Unrelated to the concrete problem, this approach is however terribly inefficient. You're not taking benefit of the powers of a relational database and instead copying the entire DB table into Java's memory and performing the comparison in Java. You should be writing SQL queries in such way that it returns exactly the information you need. In this particular case, you should be using the SQL WHERE clause instead (in a prepared statement!), so that the resultset contains exactly zero or one row.
if (resultSet.next()) {
// Login OK!
} else {
// Login fail!
}
Further, your code is also leaking DB resources by never closing them. You should be closing them in finally. Also, loading the JDBC driver on every HTTP request is unnecessary. Just load it once during webapp's/servlet's startup.
See also:
Login works only for last user in the database
JDBC always tests the last row of MySQL table?
How often should Connection, Statement and ResultSet be closed in JDBC?

Related

Cannot make XBAP cookies work

I am trying to make a XBAP application communicating with a webservice with login.
But I want the user to skip the login step if they already logged in the last seven days.
I got it to work using html/aspx.
But it fails continuously with XBAP.
While debugging, the application is given full trust.
This is the code I have so far to write the cookie:
protected static void WriteToCookie(
string pName,
Dictionary<string, string> pData,
int pExiresInDays)
{
// Set the cookie value.
string data = "";
foreach (string key in pData.Keys)
{
data += String.Format("{0}={1};", key, pData[key]);
}
string expires = "expires=" + DateTime.Now.AddDays(pExiresInDays).ToUniversalTime().ToString("r");
data += expires;
try
{
Application.SetCookie(new Uri(pName), data);
}
catch (Exception ex)
{
}
}
And this is what I have to read the cookie:
protected static Dictionary<string, string> ReadFromCookie(
string pName)
{
Dictionary<string, string> data = new Dictionary<string, string>();
try
{
string myCookie = Application.GetCookie(new Uri(pName));
// Returns the cookie information.
if (String.IsNullOrEmpty(myCookie) == false)
{
string[] splitted = myCookie.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
string[] sub;
foreach(string split in splitted)
{
sub = split.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (sub[0] == "expires")
{
continue;
}
data.Add(sub[0], sub[1]);
}
}
}
catch(Exception ex)
{
}
return data;
}
The pName is set with:
string uri = "http://MyWebSiteName.com";
When the user authenticate the first time, I call the WriteToCookie function and set it with 7 days to expire.
It looks like everything is fine as I get no exception of error messages. (I have a break point in the catch)
After that, I close the session and start it again.
The first thing I do is a ReadFromCookie.
Then I get an exception with the following message: No more data is available
So my application is sending the user automatically back to the login screen.
I also tried to do a ReadFromCookie right after the WriteToCookie in the same session, and I get the same error.
Application.SetCookie(new Uri("http://MyWebSiteName.com/WpfBrowserApplication1.xbap"), "Hellllo");
string myCookie2 = Application.GetCookie(new Uri("http://MyWebSiteName.com/WpfBrowserApplication1.xbap"));
It seems to me that the cookie is not even written in the first place.
So I am guessing I am doing something wrong.
Maybe the uri I am using is wrong. Is there a specific format needed for it?
Just like you need a very specific format for the expire date.
I have been searching quite a lot of internet for a good sample/tutorial about using cookies with XBAP, and I could not find anything really well documented or tested.
A lot of people say that it works, but no real sample to try.
A lot of people also handle the authentication in html, then go to the XBAP after successfully reading/writing the cookies.
I would prefer a full XBAP solution if possible.
To answer some questions before they are asked, here are the project settings:
Debug:
Command line arguments: -debug -debugSecurityZoneURL http://MyWebSiteName.com "C:\Work\MyWebSiteName\MyWebSiteNameXBAP\bin\Debug\MyWebSiteNameXBAP.xbap"
Security:
Enable ClickOnce security settings (Checked)
This is a full trust application (selected)
I also created a certificate, and added it the 3 stores like explained in "publisher cannot be verified" message displayed
So I do not have the warning popup anymore. I just wanted to make sure that it was not a permission issue.
Finally found the answer to this problem.
Thanks for this CodeProject I was finally able to write/read cookies from the XBAP code.
As I had guessed, the URI needs to be very specific and you cannot pass everything you want in it.
What did the trick was using: BrowserInteropHelper.Source
In the end the read/write code looks like:
Application.SetCookie(BrowserInteropHelper.Source, data);
string myCookie = Application.GetCookie(BrowserInteropHelper.Source);
It looks like you cannot use ';' to separate your own data.
If you do so, you will only get the first entry in your data.
Use a different separator (ex: ':') and then you can get everything back
The data look like this:
n=something:k=somethingElse;expires=Tue, 12 May 2015 14:18:56 GMT ;
The only thing I do not get back from Application.GetCookie is the expire date.
Not sure if it is normal or not. Maybe it is flushed out automatically for some reason. If someone knows why, I would appreciate a comment to enlighten me.
At least now I can read/write data to the cookie in XBAP. Yeah!

Display message to user on expired session when using wicket-auth-roles

Hi I have been unable to solve the following problem in Wicket 6.*:
In our webapp we are using wicket-auth-roles to manage authentication/authorization. When session expires, user should be redirected to a page set by getApplicationSettings().setPageExpiredErrorPage(SomePage.class) on his next action. However, if the user tries to access a page which doesn't allow guests, he is redirected to a login page skipping the PageExpiredPage altogether.
My question is - how can I display "Session has expired." message to the user?
Among other things, I have tried session.info("message") during onInvalidate phase of session's lifecycle, however the feedback message is then rendered on the first page after login (not on the login page).
Thank you for your anwsers.
You could use a RequestCycleListener to record when a PageExpiredException is thrown.
public class ExceptionMapperListener extends AbstractRequestCycleListener {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
if (ex instanceof PageExpiredException) {
// Record in session or request cycle
// OR
// Create a RenderPageRequestHandler yourself and add a page parameter
// See DefaultExceptionMapper#internalMap(Exception)
}
return null;
}
}
// In Application#init():
getRequestCycleListeners().add(new ExceptionMapperListener());
ORINAL ANSWER
(kept because it could still help...)
I haven't tried it myself since I don't use wicket-auth-roles, but try overriding the method AuthenticatedWebApplication#restartResponseAtSignInPage() with something like this:
if (isSessionExpired()) {
PageParameters params = new PageParameters();
params.add("showSessionExpired", true);
throw new RestartResponseAtInterceptPageException(getSignInPageClass(), params);
} else {
throw new RestartResponseAtInterceptPageException(getSignInPageClass());
}
And then in the SignInPageClass, display the desired message if the showSessionExpired page parameter is present.
I'm not sure how you implement isSessionExpired(), but you seem to have that part already covered.
OR
Depending on how you implemented isSessionExpired(), maybe you could do the following in your SignInPageClass:
if (sessionExpired()) {
session.info("message")
}
After bernie put me on the right path, I eventually figured out a solution to the problem:
First it is required to override RequestCycleListener:
public class SessionExpiredListener extends AbstractRequestCycleListener {
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) {
if (handler instanceof IPageRequestHandler) {
IPageRequestHandler pageHandler = (IPageRequestHandler) handler;
HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();
//check whether the requested session has expired
boolean expired = request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid();
//check whether the requested page can be instantiated with the current session
boolean authorized = Session.get().getAuthorizationStrategy().isInstantiationAuthorized(pageHandler.getPageClass());
if (expired && !authorized) {
throw new PageExpiredException("Session has expired!");
}
}
super.onRequestHandlerResolved(cycle, handler);
}
}
Check for authorized prevents the session-expired message from displaying on log-out or when accessing unprotected pages.
Finally, you must register your listener and PageRequestHandlerTracker in your WebApplication:
getRequestCycleListeners().add(new SessionExpiredListener());
getRequestCycleListeners().add(new PageRequestHandlerTracker());

JUnit needs special permissions?

My builds have been failing due to some of the integration tests I've been running. I'm stuck on why it won't work. Here is an example of the output:
I'm using Maven to first build, then it calls the JUnit tests. I'm seeing this 401 Unauthorized message in every single test, and I believe that's what is causing the builds to fail. In my mind, this means there are some permissions / authentication parameters that need to be set. Where would I go about doing this in JUnit?
Edit
#Test
public void testXmlHorsesNonRunners() throws Exception {
String servletUrl = SERVER + "sd/date/2013-01-13/horses/nonrunners";
Document results = issueRequest(servletUrl, APPLICATION_XML, false);
assertNotNull(results);
// debugDocument(results, "NonRunners");
String count = getXPathStringValue(
"string(count(hrdg:data/hrdg:meeting/hrdg:event/hrdg:nonrunner/hrdg:selection))",
results);
assertEquals("non runners", "45", count);
}
If you can, try to ignore the detail. Effectively, this is making a request. This is a sample of a test that uses the issueRequest method. This method is what makes HTTP requests. (This is a big method, which is why I didn't post it originally. I'll try to make it as readable as possible.
logger.info("Sending request: " + servletUrl);
HttpGet httpGet = null;
// InputStream is = null;
DefaultHttpClient httpclient = null;
try {
httpclient = new DefaultHttpClient();
doFormLogin(httpclient, servletUrl, acceptMime, isIrishUser);
httpGet = new HttpGet(servletUrl);
httpGet.addHeader("accept", acceptMime);
// but more importantly now add the user agent header
setUserAgent(httpGet, acceptMime);
logger.info("executing request" + httpGet.getRequestLine());
// Execute the request
HttpResponse response = httpclient.execute(httpGet);
// Examine the response status
StatusLine statusLine = response.getStatusLine();
logger.info(statusLine);
switch (statusLine.getStatusCode()) {
case 401:
throw new HttpResponseException(statusLine.getStatusCode(),
"Unauthorized");
case 403:
throw new HttpResponseException(statusLine.getStatusCode(),
"Forbidden");
case 404:
throw new HttpResponseException(statusLine.getStatusCode(),
"Not Found");
default:
if (300 < statusLine.getStatusCode()) {
throw new HttpResponseException(statusLine.getStatusCode(),
"Unexpected Error");
}
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
Document doc = null;
if (entity != null) {
InputStream instream = entity.getContent();
try {
// debugContent(instream);
doc = documentBuilder.parse(instream);
} catch (IOException ex) {
// In case of an IOException the connection will be released
// back to the connection manager automatically
throw ex;
} catch (RuntimeException ex) {
// In case of an unexpected exception you may want to abort
// the HTTP request in order to shut down the underlying
// connection and release it back to the connection manager.
httpGet.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
instream.close();
}
}
return doc;
} finally {
// Release the connection.
closeConnection(httpclient);
}
I notice that your test output shows HTTP/1.1 500 Internal Server Error a couple of lines before the 401 error. I wonder if the root cause could be hiding in there. If I were you I'd try looking for more details about what error happened on the server at that point in the test, to see if it could be responsible for the authentication problem (maybe the failure is in a login controller of some sort, or is causing a session to be cancelled?)
Alternately: it looks like you're using the Apache HttpClient library to do the request, inside the issueRequest method. If you need to include authentication credentials in the request, that would be the code you'd need to change. Here's an example of doing HTTP Basic authentication in HttpClient, if that helps. (And more examples, if that one doesn't.)
(I'd second the observation that this problem probably isn't specific to JUnit. If you need to do more research, I'd suggest learning more about HttpClient, and about what this app expects the browser to send. One possibility: use something like Chrome Dev Tools to peek at your communications with the server when you do this manually, and see if there's anything important that the test isn't doing, or is doing differently.
Once you've figured out how to login, it might make sense to do it in a #Before method in your JUnit test.)
HTTP permission denied has nothing to do with JUnit. You probably need to set your credentials while making the request in the code itself. Show us some code.
Also, unit testing is not really meant to access the internet. Its purpose is for testing small, concise parts of your code which shouldn't rely on any external factors. Integration tests should cover that.
If you can, try to mock your network requests using EasyMock or PowerMock and make them return a resource you would load from your local resources folder (e.g. test/resources).

How to redirect to the login page when the session expires?

I have three JSF 2.0 web modules and I need to redirect to the login page when the session expires.
I have tried it using a HttpSessionListener, it is calling the sessionDestroyed() event method, but I am not able to forward/redirect the request in there. I think it is becasue there are no HttpServletRequest and HttpServletResponse objects.
I also tried it using a PhaseListener, but it results in a "too many redirects" error in the webbrowser.
public class SessionListener implements PhaseListener {
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
public void beforePhase(PhaseEvent event) {
if (!FacesContext.getCurrentInstance().isPostback()) {
try {
System.out.println("Session Destroyed");
FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
}
catch (Exception e) {
System.out.println("error" + e);
}
}
}
public void afterPhase(PhaseEvent event) {
try {
System.out.println("Session Created");
}
catch (Exception e) {
System.out.println("error" + e);
}
}
}
Why do those attempts not work and how can I solve it the best?
It's not possible to send a redirect at exactly the moment when the session is expired. The client has namely not sent any HTTP request at that moment which you could then respond with a redirect.
You should just keep your existing authentication mechanism which redirects to the login page when the user is not logged-in anymore. You can at best improve it by adding a check if the user is been redirected to the login page because the session has been expired, or just because he has never logged in before (i.e. it's a fresh new request).
You can check for that by if HttpServletRequest#getRequestedSessionId() doesn't return null (which means that the client has sent a session cookie and thus assumes that the session is still valid) and HttpServletRequest#isRequestedSessionIdValid() returns false (which means that the session has been expired at the server side). You can do that in the very same filter where you're checking for the logged-in user (you do already have one, right? or are you using container managed authentication?).
User user = (User) session.getAttribute("user");
if (user == null) {
String loginURL = request.getContextPath() + "/login.jsf";
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
response.sendRedirect(loginURL + "?expired=true");
} else {
response.sendRedirect(loginURL);
}
} else {
chain.doFilter(request, response);
}
And then in the login.xhtml page check for it
<h:panelGroup rendered="#{param.expired}">
<p>You have been redirected to the login page, because your session was expired.</p>
</h:panelGroup>
Your phase listener approach makes by the way no sense. It indeed sends a redirect on every single request causing it to run in an infinite loop. The restore view phase has absolutely nothing to do with the session expiration.
Try to use
FacesContext.getCurrentInstance().getApplication().getNavigationHandler().
handleNavigation(context, null, "LoginForm");
But note that you should use Servlet Filter for these purposes, it's better to do not any redirection from PhaseListener because it's really error prone.

Blob into Oracle: about 15% are filled with \00

Under Weblogic 10, I am using Hibernate to store data into several tables with BLOBs. It's always worked fine but the customer found specific circumstances where 15% of the BLOBs have the correct size but only contain null characters. I can't figure out what makes it good or full of emptiness.
The BLOB type I am using does a:
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, sqlTypes()[0]);
return;
}
try {
Connection conn = st.getConnection();
if (conn instanceof org.apache.commons.dbcp.DelegatingConnection) {
log.debug("Delegating connection, digging for actual driver");
conn = ((org.apache.commons.dbcp.DelegatingConnection)st.getConnection()).getInnermostDelegate();
}
OutputStream tempBlobWriter = null;
BLOB tempBlob = BLOB.createTemporary(conn, true, BLOB.DURATION_SESSION);
try {
tempBlob.open(BLOB.MODE_READWRITE);
tempBlobWriter = tempBlob.setBinaryStream(1L);
tempBlobWriter.write((byte[])value);
tempBlobWriter.flush();
} finally {
if (tempBlobWriter != null)
tempBlobWriter.close();
tempBlob.close();
}
st.setBlob(index, (Blob) tempBlob);
} catch (IOException e) {
throw new HibernateException(e);
}
}
I put a log in there and can confirm that the value (byte[]) is good. I tried to change the createTemporary parameters, no success.
I am running this under Weblogic 10.0 (can't upgrade that) with the bundled Oracle Thin driver.
A clue is that the working calls come from the standard web service deployed and managed by WLS. But the problematic calls are done from a thread started along with the component that interfaces with some legacy system with JNI. This thread works like a charm for everything except these BLOBs. I am getting a new Session just before inserting the data and closing it a bit after. (The Session does NOT remain open for the lifetime of the thread)
I have set the Hibernate log level to DEBUG but it does not give me any clue. I'm starting to run out of ideas...
Problem solved.
In fact, I was doing:
open session
open transaction
get first item from legacy system
write first item to database (blob)
close transaction
open transaction
get second item from legacy system
write second item to database (blob)
close transaction
... until the legacy system has nothing more to process
close session
This would typically process between 1 and 5 items per round.
But because the Oracle driver does not use the standard way of handling blobs in JDBC, our custom type has to create a temporary blob that is stored in the session. And apparently when you're inserting blobs in differents transactions within the same session, they tend to interfere and cause my problem.
I solved it by closing the session after each commit. I do not like it but I consider it being the Oracle driver's fault.

Resources