Chapter 8: Authentication

From Documentation

Target Application

In this chapter, we will demonstrate how to implement authentication and protect your pages from illegal access. We will create a login page without sidebar as follows:

Tutorial-ch8-login.png


After login, we redirect users to index page with user name appeared at right side of the header.

Tutorial-ch8-index.png

Authentication

Authentication is the process to identify a user, and requesting an account and a password is a common way. Our login page also uses a template zul to keep a consistent style with index page. But it has no sidebar because users without login should not access main functions.

/chapter8/layout/template-anonymous.zul

<zk>
	<!-- free to access template, without sidebar  -->
	<borderlayout hflex="1" vflex="1">
		<north height="100px" border="none" >
			<include src="/chapter8/layout/banner.zul"/>
		</north>
		<center id="mainContent" autoscroll="true" border="none" self="@insert(content)">
			<!-- the main content will be insert to here -->
		</center>
		<south height="50px" border="none">
			<include src="/chapter3/footer.zul"/>
		</south>
	</borderlayout>
</zk>
  • Line 7: Define an anchor named content


Login form is built with Grid.

/chapter/8/login.zul

<?link rel="stylesheet" type="text/css" href="/style.css"?>
<!-- it is a login page, no authentication protection and use anonymous template -->
<?init class="org.zkoss.zk.ui.util.Composition" arg0="/chapter8/layout/template-anonymous.zul"?>
<zk>
	<hbox self="@define(content)" vflex="1" hflex="1" align="center"
		pack="center" spacing="20px">
		<vlayout>
			<window id="loginWin"
				apply="org.zkoss.tutorial.chapter8.LoginController"
				title="Login with you name" border="normal" hflex="min">
				<vbox hflex="min" align="center">
					<grid hflex="min">
						<columns>
							<column hflex="min" align="right" />
							<column />
						</columns>
						<rows>
							<row>
								Account :
								<textbox id="account" width="200px" />
							</row>
							<row>
								Password :
								<textbox id="password" type="password"
									width="200px" />
							</row>
						</rows>
					</grid>
					<label id="message" sclass="warn" value="&#160;" />
					<button id="login" label="Login" />
					
				</vbox>
			</window>
			(use account='zkoss' and password='1234' to login)
		</vlayout>
	</hbox>
</zk>
  • Line 3: Apply a template zul with <?init ?>.
  • Line 5: Define a fragment to be inserted in the anchor content.
  • Line 24: Specify "password" at type, then user input will be masked.


Understand Session

Before proceeding to implement login function, we have to understand "session" first. A web application operates over HTTP protocol which is stateless; each request and its corresponding response is handled independently. Hence, a HTTP server cannot know whether a series of request sent from the same client or from different clients. That means the server cannot maintain client's state between multiple requests.

For HTTP protocol's characteristic, application servers maintain a session to keep client's state. When the server receives the first request from a client, the server creates a session and give the session a unique identifier. The client should send a request with the session identifier. The server can determine which session the request belongs to upon this session identifier.

In Java EE environment, an application server creates a javax.servlet.http.HttpSession object to track client's session. ZK's Session is a wrapper of HttpSession, you can use it to store user's data when you handle events. The usage:

  • Get current session: Sessions.getCurrent()
  • Store data into a session: Session.setAttribute("key", data)
  • Retrieve data from a session: Session.getAttribute("key")

Login

After understanding basic concept and usage, we can start to create a controller for login. This controller collects account and password input and validate them with a authentication service class. If the password is correct, the authentication service class saves user's credential into the session.

Controller used in chapter8/login.zul

public class LoginController extends SelectorComposer<Component> {
	
	//wire components
	@Wire
	Textbox account;
	@Wire
	Textbox password;
	@Wire
	Label message;
	
	//services
	AuthenticationService authService = new AuthenticationServiceChapter8Impl();

	
	@Listen("onClick=#login; onOK=#loginWin")
	public void doLogin(){
		String nm = account.getValue();
		String pd = password.getValue();
		
		if(!authService.login(nm,pd)){
			message.setValue("account or password are not correct.");
			return;
		}
		UserCredential cre= authService.getUserCredential();
		message.setValue("Welcome, "+cre.getName());
		message.setSclass("");
		
		Executions.sendRedirect("/chapter8/");
		
	}
}
  • Line 20: Authenticate a user with account and password and save user's credential into the session if it passes.
  • Line 28: Redirect to index page after successfully authenticated.


public class AuthenticationServiceChapter8Impl extends AuthenticationServiceChapter5Impl{

	
	UserInfoService userInfoService = new UserInfoServiceChapter5Impl();
	
	@Override
	public boolean login(String nm, String pd) {
		User user = userInfoService.findUser(nm);
		//a simple plan text password verification
		if(user==null || !user.getPassword().equals(pd)){
			return false;
		}
		
		Session sess = Sessions.getCurrent();
		UserCredential cre = new UserCredential(user.getAccount(),user.getFullName());
		//just in case for this demo.
		if(cre.isAnonymous()){
			return false;
		}
		sess.setAttribute("userCredential",cre);
		

		return true;
	}
	...
}
  • Line 14: Get the current session.
  • Line 20: Store user credential into the session with a key userCredential which is used to retrieve credential back in the future.

Logout

Secure Your Pages

Security is an important issue that every developer must consider for a web application since users can enter any URL in a browser to access any resource. Even though you have created a login page for authentication, but a user can bypass the login page and access the index page after login if he knows the page's URL. Therefore, we should apply a mechanism to protect zul pages from illegal access. ZK allows you to initialize a zul page by implement a Initiator. When we apply an Initiator to a zul, ZK will use it to perform initialization before creating components upon a zul. We can create a initiator to check user's