hi friends
today we want talk about cookies and work with them in Servlets
as we know cookies is used for storing something (text) on client machine and us it again
for example store username and password for preventing re login to system
or storing page color schema or something like that
the cookies structure
cookies have got...
1:name & value
each cookie has a name that we know its with this and also has a value
for example a cookie with 'email' name attribute, with 'x@x.x' value
2:expire time
each cookie has a expire time, if you omit this attribute, the cookie will remove by closing the browser or we called it session cookie
3:path & domain
these attributes usually use for limit the accessibility, what do I mean? look for example if you (for example) set path = '/' and domain='.sun.com', then all sub domains from any directory can access to this cookie
or set path ='/java' and domain ='java.sun.com', so it means just directories under 'java.sun.com/java' can access to this guy
4:secure & version
secure attribute accept a false(default) or true value, when we set it as true, it means this cookie just accessible through a secure connection(such as https), version attribute shows the cookie's version
now we want use cookies from Servlets, add, delete, update...
okay as always as ever lets talk it with an example
example:
a servlet for checking cookies and also for sign in
for example imagine this (_Servlets.RegLog.java) file, we will look at it step by step
(download war file + sources )+ | -package _Servlets;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//@author ArAsh M. Dehghani
public class RegLog extends HttpServlet {
private Cookie[] cooks;
private _Validators._chkUser checkUser=new _Validators._chkUser();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();
try {
cooks=request.getCookies();
out.println("<html>");
out.println("<head>");
out.println("<title>Login or Registration</title>");
out.print("<link rel=\"stylesheet\" type=\"text/css\" href=\"./resources/_pageSchema.css\"/>");
out.println("</head>");
out.println("<body><div><br/>");
if(!this.checkCooks()){
out.println("<table style=\"vertical-align:top\"><tr><td><big><b>Login</big></b></td><td><big><b>Registration</big></b></td></tr>");
out.print("<tr><td>"+this.drawLogin()+"</td><td>"+this.drawRegister()+"</td></tr></table>");
}
else{out.print("Welcome "+checkUser.getName()+" <form id=\"lof\" action=\"./logoff\" method=\"post\"><a href=\"#\" onclick=\"javascript:document.getElementById('lof').submit()\"><small>[log off]</small></a> | <a href=\"./feedback\"><small>feedback</small></a></form>");
}
out.println("</div></body>");
out.println("</html>");
}catch(Exception e){out.print(e);}
finally {
out.close();
}}
private boolean checkCooks(){
if(Arrays.equals(this.cooks,null)){return false;}
for(Cookie c:cooks){
if(c.getName().equals("loginUser")){this.checkUser.SetU(c.getValue());continue;}
if(c.getName().equals("loginPass")){this.checkUser.setP(c.getValue());continue;}
}
return this.checkUser.validate();
}
@Override
@SuppressWarnings("empty-statement")
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getParameter("uName").equals(null) || request.getParameter("pWord").equals(null)){doGet(request,response);return;}
checkUser.SetU(request.getParameter("uName"));checkUser.setPass(request.getParameter("pWord"));
response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();
try{out.println("<html>");
out.println("<head>");
out.println("<title>login</title>");
out.print("<link rel=\"stylesheet\" type=\"text/css\" href=\"./resources/_pageSchema.css\"/>");
out.println("</head>");
out.println("<body><div><br/>");
if(!checkUser.validate()){out.print("<span style=\"color:maroon\">Invalid username or password <a href=\"./login\">[try again]</a></span>");
out.println("</div></body>");
out.println("</html>");}
else{Cookie name=new Cookie("loginUser", request.getParameter("uName"));
Cookie pass=new Cookie("loginPass", checkUser.code());
response.addCookie(name);
response.addCookie(pass);
response.sendRedirect("./login");
}
}finally{out.close();}
}
private String drawRegister(){
String re="<form action=\"./register\" method=\"post\"><br/>* = required fields";
re +="<table><tr><td>Name</td><td><input type=\"text\" class=\"inputText\" name=\"name\"/></td></tr>";
re += "<tr><td>Last Name *</td><td><input type=\"text\" class=\"inputText\" name=\"lName\"/></td></tr>";
re +="<tr><td>Username *</td><td><input type=\"text\" class=\"inputText\" name=\"user\"/></td></tr>";
re +="<tr><td>Password *</td><td><input type=\"password\" class=\"inputText\" name=\"pass0\"/> | Verify <input type=\"password\" class=\"inputText\" name=\"pass1\"/></td></tr>";
re +="<tr><td>Phone</td><td><input type=\"text\" class=\"inputText\" name=\"phone\"/></td></tr>";
re +="<tr><td></td><td><input type=\"submit\" value=\"create\" style=\"buttons\"/></td></tr></table></form>";
return re;
}
private String drawLogin(){
String re="<form method=\"post\"><br/>";
re +="<table><tr><td>Username</td><td><input type=\"text\" class=\"inputText\" name=\"uName\"/></td></tr>";
re +="<tr><td>Password</td><td><input type=\"password\" class=\"inputText\" name=\"pWord\"/></td></tr>";
re +="<tr><td></td><td><input type=\"submit\" value=\"log in\" style=\"buttons\"/></td></tr></table></form>";
return re;}
}
okay now lets separate above code and explain about them
lets start with doGet() method
this method called when you request ./login, this method after authorizing via _chkUser class says welcome or provide login or registration form
...
private Cookie[] cooks;
...
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();
try {
cooks=request.getCookies(); //[0]
out.println("<html>");
out.println("<head>");
out.println("<title>Login or Registration</title>");
out.print("<link rel=\"stylesheet\" type=\"text/css\" href=\"./resources/_pageSchema.css\"/>");
out.println("</head>");
out.println("<body><div><br/>");
if(!this.checkCooks()){ //[1]
out.println("<table style=\"vertical-align:top\"><tr><td><big><b>Login</big></b></td><td><big><b>Registration</big></b></td></tr>");
out.print("<tr><td>"+this.drawLogin()+"</td><td>"+this.drawRegister()+"</td></tr></table>");
}
else{out.print("Welcome "+checkUser.getName()+" <form id=\"lof\" action=\"./logoff\" method=\"post\"><a href=\"#\" onclick=\"javascript:document.getElementById('lof').submit()\"><small>[log off]</small></a> | <a href=\"./feedback\"><small>feedback</small></a></form>");
}//[2]
out.println("</div></body>");
out.println("</html>");
}catch(Exception e){out.print(e);}
finally {out.close();}
}
in above code
[0]:getCookies() method returns an array of cookies, this method get all cookies from client machine
[1]:checkCooks() method, we'll talk about it
[2]:if checkCooks returns true, it means user did logged in before, so say welcome
[2]:checkUser.getName(), this will return a String object that shows current user full name, we'll talk about it
checkCooks() method
this method catching cookies values and pass them to _chkUser if exist, and return a boolean values, true means user logged in
...
private _Validators._chkUser checkUser=new _Validators._chkUser();
...
private boolean checkCooks(){ //[0]
if(Arrays.equals(this.cooks,null)){return false;} //[1]
for(Cookie c:cooks){ //[2]
if(c.getName().equals("loginUser")){this.checkUser.SetU(c.getValue());continue;} //[3]
if(c.getName().equals("loginPass")){this.checkUser.setP(c.getValue());continue;}//[4]
}
return this.checkUser.validate();//[5]
}
in above code
[0]:method returns a boolean value,true means user logged in
[1]:checking are there any cookies in client machine?
NOTE: Remember, getCookies() method gets all cookies from client machine and return an array of them, IF there isn't any cookie in client it returns null
NOTE: Remember, always checking the null equality an array with Arrays.equals(arrayObject,compairObject) method (!no arrayObject.equals())
[2]:if a for loop find wanted cookies
[3]:looking for 'loginUser' and 'loginPass' cookies, and pass the values to _chkUser class
[4]:Remember don't use (for example) cooks[0].getValue(), because my cooks[0] isn't 'loginUser', may be another thing like 'colorSchema'
[5]:the validate() method will authorize user
doPost() method
this method provides login operation, at the first check and authorize user, if user exists then send cookies to client machine for auto login for next session
...
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getParameter("uName").equals(null) || request.getParameter("pWord").equals(null)){doGet(request,response);response.sendRedirect("./login");} //[0]
checkUser.SetU(request.getParameter("uName"));checkUser.setPass(request.getParameter("pWord")); //[1]
response.setContentType("text/html;charset=UTF-8");PrintWriter out = response.getWriter();
try{
if(!checkUser.validate()){ //[2]
out.println("<html>");
out.println("<head>");
out.println("<title>login</title>");
out.print("<link rel=\"stylesheet\" type=\"text/css\" href=\"./resources/_pageSchema.css\"/>");
out.println("</head>");
out.println("<body><div><br/>");
out.print("<span style=\"color:maroon\">Invalid username or password <a href=\"./login\">[try again]</a></span>");
out.println("</div></body>");
out.println("</html>");}
else{Cookie name=new Cookie("loginUser", request.getParameter("uName")); //[3]
Cookie pass=new Cookie("loginPass", checkUser.code());//[4]
response.addCookie(name); //[5]
response.addCookie(pass); //[6]
response.sendRedirect("./login"); //[7]
}
}finally{out.close();}
}
in above code
[0]:at the first check both username and password attribute filled, if not redirect
[1]:pass the parameter to _chkUser class for authorizing
[2]:if user doesn't exists or invalid username or password entered, system will show message and link for try again
[3]:if user exist, now create cookies and send it to client
NOTE: Cookie class is a very simple class, because cookies are simple too, while you creating an instance of Cookies, REMEMBER set the cookies name by its constructor, because there isn't any setter method for set name, as this 'Cookie myC=new Cookie('cookieName','CookieValue')'
NOTE([4]):this is a strong and may necessary code the information while you want send it to client machine for Security issues
for example, if a user logged in to system and you set and send the cookies as this 'loginName=arash','loginPass=crazy', it's completely unsecured, because Arash's friends will can find username and password and login to system with Arash's accounts
so for this problem we code the values when we want send it to client and decode at server for having original value
[5]:addCookie(), this method sends (get ready) a cookie to client, we can do it in multi times [6]
[7]:after setting and sending, redirect the browser, this servlet will call itself then doGet method run and authorize the user, and says Welcome instead of login form
do more with cookies
as we said cookies have expire date, so how to set it?
after creating cookie, use setMaxAge(int second) for set expire time
for example
...
myCookie.setMaxAge(60); //[1]
...
[1]: this cookie will destroy(expire) after 60 'SECOND'
another example
the following cookie will destroy (expire) after 1 day since now
...
myCookie.setMaxAge(60*60*24);
...
NOTE:
if you pass a negative value for example
...
myCookie.setMaxAge(-1);
...
it means cookie will remove by closing browser, it's default value, if you don't set it, the cookie will expire with closing browser by default
and if you pass 0 (zero) value, it means remove the cookie immediately
...
myCookie.setMaxAge(0);
//cookie removed
...
work with setPath() and setDomain() attributes
as we said we have 2 attributes in cookies 'path' and 'domain'
Very Important NOTE: if your project is local, it's really important set the path and domain value, why?
for example 3 war file has deployed on Mr. Tomcat, well if you set the path as '/' then all of the deployed project will can access to the a same cookie, it may be cool for sharing a cookie between some project, but if you want deny access for other project, you should set the cookie's path as '/MyProjectContextPath'
and also about domain, for example we have 2 war file with the same context path on 2 difference server, 'tomcat' & 'glassfish', now we should set the domain for deny access for each other
example
with setPath() method we can do cool things
...
Cookie inboxCookie=new Cookie("colorSchema","black");
inboxCookie.setPath(request.getContextPath()+"/inbox"); //[0]
inboxCookie.setDomain(".localhost:1321"); //[1]
Cookie homeCookie=new Cookie("colorSchema","blue");//[2]
homeCookie.setPath(request.getContextPath()+"/home");
homeCookie.setDomain("localhost"); //[3]
...
in above code
inboxCookie will be accessible for '*.localhost:1321/webApp0/inbox/*', means from any sub domain, from /inbox directory and sub directory
[0]:with getContextPath() method we can get the context path (/webApp0)
[1]:as we see while setting domain I added :1321 port, this is Tomcat port number, if you omit, glassfish and JBoss AS will can access to this guy
homeCookies will be accessible for '*.localhost/webApp0/home/*', means from any sub domain, from /home directory and sub domains
Very Important NOTE([2]):by default if (for example) there is a cookie 'colorSchema' stored in client with '/' path value and '.localhost' domain value, if a new cookie with same name ('colorSchema') send to the client machine and the path and domain values were equal to old path and domain values, then the previous cookie will update with new values
another method is setVersion(), with this method we can set the current version of the cookie, so does it useful? completely useful
okay imagine your system provides dis-active & re-active operation, something like Facebook
well may at the client, user has 3 browser (FF,Opera,Chrome) and logged to system with all of them
for example user dis-active own account via Opera, so it means cookies from opera removed but still we have cookies in Chrome and FF, and system should deny access auto login with cookies for FF or chrome because user dis-active account, for something problem like this we set the version for cookies, then after dis-active the account with Opera, user tries to login with FF, but system checks the version and yes, version is unavailable for logging in
example
...
Cookie rc=new Cookie("test","rock");
rc.setVersion(1);//[0]
...
[0]: remember setVersion() gets an integer value for setting cookie's version not an string
I hope this article were useful for you