Blank window with IE & firefox after re-login (form based authentication).

Hi,

I’m quite new to the Vaadin toolkit and I’m finishing my first application with it. I’m in point where I need to add authentication to the application. I’m running on weblogic and using custom security realm with form based authentication.

For login, I use jsp-page that posts normally to the j_security_check and after succesfull login user is forwarded to my Vaadin application.

I’m doing programmatic logout using weblogic.servlet.security.ServletAuthentication.logout(HttpServletRequest request) and weblogic.servlet.security.ServletAuthentication.invalidateAll(HttpServletRequest request).

After logout user is forwarded back to the login page but when the user tries to do the re-login from the login-page I get blank screen with IE and Firefox. In Google Chrome my Vaadin application is opened in correct way at this point.

In browser address bar there is following visible address: http://myserver/myapp/UIDL/?windowName=1946600943&onunloadburst=1. If I remove the UIDL part from the address bar after login, my Vaadin application runs normally.

Any ideas where I might go wrong?

I have similar problem with Spring Security (also form login). I logout normal spring security way.

I guess value of windowName parameter is wrong.

This was caused by Spring security remembering the last request URL it saw (which in this case is the “window closed” message), and login re-executing that request for an already closed application rather than opening a new application.

Fixed for Spring security in http://dev.vaadin.com/ticket/3157, fix may also apply to other similar authentication frameworks.

This fix also repairs JEE form login authentication. Tested with Jetty 6x but I guess this fix is working other application servers as well.

I tested this again with nightly build and I still got the same problem. I tested with spring security and it works but by using it I will face other problems related the custom realm.

Is there a better way to access the HTTPServletRequest in my LoginHandler class than getting it with thread pattern? My current implementation feels a bit uggly.

In my application class I have following:


private HttpServletRequest request;

/*
 *  Set ThreadLocal application.
 *  @param ExampleApplication t	
 */
public static void setProject(MyApplication) {
	thisApplication.set(t);
}

/*
 *  Get ThreadLocal application.
 */
public static MyApplication getProject() {
	return thisApplication.get();
}

/*
 * For ThreadLocal pattern.
 */
public void transactionStart(Application application, Object transactionData) {
	request = (HttpServletRequest)transactionData;
	if (application == MyApplication.this) {
		thisApplication.set(this);
	}

}

public HttpServletRequest getRequest() {
	return request;
}

Then I access the request object in my LoginHandler with MyApplication.getProject().getRequest() method so I can pass it to the weblogic session invalidate method.

Should I implement application close listener and execute weblogic session invalidate methods in there?

My test application used following code in application class. It worked with Jetty 6x.

close();
getMainWindow().open(new ExternalResource(getURL().getPath()));
((WebApplicationContext)getContext()).getHttpSession().invalidate();

Hi,

I tested the logout one more time and implemented it like you described but the result is still the same. I also created simple test application to test the logout functionality and I still get the blank window after re-login.

Application:


import com.vaadin.Application;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;

public class LoginTestApplication extends Application {

	@Override
	public void init() {
		HorizontalLayout layout = new HorizontalLayout();
		
		SplitPanel splitPanel = new SplitPanel(
        SplitPanel.ORIENTATION_VERTICAL);
		splitPanel.addComponent(layout);
        setMainWindow(new Window("LoginTest", splitPanel));
        
        layout.addComponent(new Button("Logout",
                new Button.ClickListener() {
                    public void buttonClick(ClickEvent event) {
                        logout();
                    }
                }));

	}
	
	private void logout(){
		close();
		getMainWindow().open(new ExternalResource(getURL().getPath()));
		((WebApplicationContext)getContext()).getHttpSession().invalidate();
	}

}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>
	LoginTest</display-name>
		<context-param>
		<description>
		Vaadin production mode</description>
		<param-name>productionMode</param-name>
		<param-value>false</param-value>
	</context-param>

	<servlet>
		<servlet-name>LoginTestApp</servlet-name>
		<servlet-class>
		com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
		<init-param>
			<description>
			Vaadin application class to start</description>
			<param-name>application</param-name>
			<param-value>com.app.test.logintest.ui.LoginTestApplication</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>LoginTestApp</servlet-name>
		<url-pattern>/client/*</url-pattern>
	</servlet-mapping>
	
	<servlet-mapping>
		<servlet-name>LoginTestApp</servlet-name>
		<url-pattern>/VAADIN/*</url-pattern>
	</servlet-mapping>
	
	<welcome-file-list>
		<welcome-file>/client/open</welcome-file>
	</welcome-file-list>

	<security-constraint>
       <web-resource-collection>
            <web-resource-name>SecuredPages</web-resource-name>
            <url-pattern>/client/*</url-pattern>
            <http-method>POST</http-method>
            <http-method>GET</http-method>
            
        </web-resource-collection>
        
        <auth-constraint>
            <role-name>
                Users
            </role-name>
        </auth-constraint>
        
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
        
    </security-constraint>
    

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Entire Application</web-resource-name>
            <url-pattern>/login.jsp</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
        
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    
    <login-config>        
        <auth-method>FORM</auth-method>        
        <form-login-config>            
            <form-login-page>/login.jsp</form-login-page>            
            <form-error-page>/login.jsp?error=true</form-error-page>        
        </form-login-config>    
    </login-config>
    
    <security-role>
        <role-name>
            Users
        </role-name>
    </security-role> 

</web-app>

I quickly test with Weblogic 10.3 and it worked. I downloaded latest
nightly build
. Login works for all Weblogic Administrators like weblogic.

Java source:

package test;

import com.vaadin.Application;
import com.vaadin.terminal.ExternalResource;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;

public class FormLoginApplication extends Application {

	private static final long serialVersionUID = 1L;

	@SuppressWarnings("serial")
	@Override
	public void init() {
		Window mainWindow = new Window("Form Login Application");
		Label label = new Label("Hello Vaadin user");
		mainWindow.addComponent(label);
		mainWindow.addComponent(new Button("Logout", new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				logout();
			}
		}));
		setMainWindow(mainWindow);
	}

	private void logout() {
		close();
		getMainWindow().open(new ExternalResource(getURL().getPath()));
		((WebApplicationContext) getContext()).getHttpSession().invalidate();
	}

}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>TestFormLogin</display-name>
	<context-param>
		<description>Vaadin production mode</description>
		<param-name>productionMode</param-name>
		<param-value>false</param-value>
	</context-param>
	<servlet>
		<servlet-name>Form Login Application</servlet-name>
		<servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
		<init-param>
			<description>Vaadin application class to start</description>
			<param-name>application</param-name>
			<param-value>test.FormLoginApplication</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>Form Login Application</servlet-name>
		<url-pattern>/app/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Form Login Application</servlet-name>
		<url-pattern>/VAADIN/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>/app</welcome-file>
	</welcome-file-list>
	<security-constraint>
		<web-resource-collection>
			<web-resource-name>SecuredPages</web-resource-name>
			<url-pattern>/app/*</url-pattern>
			<http-method>POST</http-method>
			<http-method>GET</http-method>
		</web-resource-collection>
		<auth-constraint>
			<role-name>Administrators</role-name>
		</auth-constraint>
		<user-data-constraint>
			<transport-guarantee>NONE</transport-guarantee>
		</user-data-constraint>
	</security-constraint>
	<login-config>
		<auth-method>FORM</auth-method>
		<realm-name>myrealm</realm-name>
		<form-login-config>
			<form-login-page>/login.jsp</form-login-page>
			<form-error-page>/login.jsp?error=true</form-error-page>
		</form-login-config>
	</login-config>
	<security-role>
		<role-name>Administrators</role-name>		
	</security-role>
</web-app>

weblogic.xml:

<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://www.bea.com/ns/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://www.bea.com/ns/weblogic/weblogic-web-app http://www.oracle.com/technology/weblogic/10.3/weblogic-web-app/1.0/weblogic-web-app.xsd">
    <wls:weblogic-version>10.3.0</wls:weblogic-version>
    <wls:security-role-assignment>
        <wls:role-name>Administrators</wls:role-name>
        <wls:principal-name>Administrators</wls:principal-name>
    </wls:security-role-assignment>
    <wls:context-root>test</wls:context-root>
    <wls:fast-swap>
        <wls:enabled>false</wls:enabled>
    </wls:fast-swap>
</wls:weblogic-web-app>

login.jsp:

<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Test Form Login</title>
</head>
<body>
	<p>You have tried to access a protected area of this application.</p>
	<form name="f" action="<%= request.getContextPath() %>/j_security_check" method="POST">
		<label for="j_username">Name:</label> <input id="j_username" type='text' name='j_username' style="width: 150px" />
		<br />
		<label for="j_password">Password:</label> <input id="j_password" type='password' name='j_password' style="width: 150px" />
		<br />
		<input id="proceed" type="submit" value="Submit" /> <input id="reset" type="reset" value="Reset" />
	</form>
</body>
</html>

Hello again.

I tested this issue with fresh domain in weblogic 10.3 and it works perfectly.

However, I tested same application also in weblogic 10.0 where I used fresh domain and it didn’t work. Sad thing is that I’m not able to use 10.3 yet.