วันจันทร์ที่ 13 กันยายน พ.ศ. 2553

การใช้ session จดจำข้อมูล

เราสามารถใช้วัตถุแฝง session จดจำข้อมูลได้คล้ายกับคุ๊กกี้ แต่แทนที่จะซ่อนข้อมูลเก่าไว้
ในฮาร์ดดิสก์ของผู้เยี่ยมชมจะใช้การเก็บข้อมูลไว้บนฝั่งเวบเซิร์ฟเวอร์แทน ข้อดีของการทำ
แบบนี้ก็คือ ในบางครั้งผู้เยี่ยมชมที่เป็นห่วงเรื่องของความปลอดภัยและความเป็นส่วนตัวจึง
กำหนดให้เบราเซอร์บนเครื่องคอมพิวเตอร์ของตนไม่ให้รับคุ๊กกี้จากเวบไซต์ การใช้ session
ทำงานแทนคุ๊กกี้จะไม่มีปัญหาตรงจุดนี้เพราะไม่มีการหยอดคุ๊กกี้ลงบนเบราเซอร์ของผู้เยี่ยม
ชมแต่ประการใด
อย่างไรก็ดี วัตถุแฝง session มี scope เป็นแบบ session ดังนั้นจึงจดจำข้อมูลของผู้เยี่ยม
ชมได้เฉพาะชั่วขณะที่ผู้เยี่ยมชมยังติดต่อกับเวบไซต์อยู่หรือตราบเท่าที่ยังไม่ปิดเบราเซอร์
เมื่อผู้เยี่ยมชมปิดการทำงานของเบราเซอร์ข้อมูลเหล่านั้นก็จะหายไป ดังนั้นการใช้ session
เก็บข้อมูลอาจจะไม่เหมาะกับการจดจำชื่อสมาชิกและรหัสลับอย่างในกรณีของคุ๊กกี้ในตัว
อย่างที่ผ่านมา แต่จะเหมาะกับการใช้จดจำว่าผู้เยี่ยมชมรายใดได้ล็อกอินไปแล้วบ้าง ตราบ
เท่าที่ผู้เยี่ยมชมรายนั้นยังไม่ปิดเบราเซอร์ผู้เยี่ยมชมไม่ต้องล็อกอินอีก

เราจะลองใช้ session กับระบบสมาชิกที่เราได้สร้างไว้ก่อนหน้านี้ โดย session จะทำหน้าที่
จดจำเบราเซอร์ที่ล็อกอินแล้ว เมื่อเวลาที่ผู้เยื่ยมชมต้องการข้ามไปดูเวบหน้าอื่น เวบหน้า
นั้นๆ จะตรวจสอบว่าผู้เยี่ยมชมล็อกอินแล้วหรือยังด้วยการสืบค้นจาก session
วัตถุแฝง session มีแมธธอสชื่อ setAttribute() และ getAttribute() ซึ่งใช้บันทึกและเรียกดู
ข้อมูลอะไรก็ได้ ดูไปแล้วก็คล้ายกับคุ๊กกี้ ลองพิจารณาโปรแกรมที่ปรับปรุงใหม่ต่อไปนี้

<% String username = request.getParameter("username");
String password = request.getParameter("password");
%>
<html>
<title>Login</title>
<body>
<% if (username.equals("Songkarn")&&password.equals("12345")) {
session.setAttribute("isLoggedin","yes");
%>
Login successful.
<% } else { %>
Login failed.
<% } %>
</body>
</html>

โปรแกรมนี้เหมือนกับโปรแกรมที่ 8-2 เพียงแต่เมื่อพบว่าชื่อและรหัสสมาชิกถูกต้อง ให้สร้าง
ตัวเก็บข้อมูลชื่อ isLoggedin ขึ้นมาโดยกำหนดให้มีค่าเท่ากับ yes ด้วยคำสั่ง setAttribute()
ตัวเก็บข้อมูลนี้จะคงอยู่ตราบเท่าที่ผู้เยี่ยมชมผู้นี้ยังไม่ปิดการทำงานของเบราเซอร์
คราวนี้เวบหน้าใดก็ตามที่เราไม่ต้องการให้ผู้เยี่ยมชมดูได้โดยไม่ล็อกอินก่อน ก็สามารถ
ตรวจสอบการล็อกอินของผู้ที่เข้ามาด้วยการใช้แมธธอส getAttribute() เพื่อตรวจดูว่า
session ของผู้เยี่ยมชมรายนั้นๆ มีตัวเก็บข้อมูลชื่อ isLoggedin อยู่หรือไม่ และมีค่าเท่ากับ
yes หรือเปล่า
ลองสร้างไฟล์ .jsp ขึ้นมาไฟล์หนึ่งโดยสมมติว่าเป็นเวบเพจหน้าที่ต้องการมีการล็อกอินก่อน
ซึ่งจะดูได้ ดังนี้


<% String isLoggedin = new String();
if (session.getAttribute(“isLoggedin”)!=null) isLoggedin =
(String)session.getAttribute(“isLoggedin”);
%>
<html>
<title>Sample Page</title>
<body>
<% if (isLoggedin.equals(“yes”)) { %>
Welcome. You are authorized to view this page. <br>
The money in your account is now $500.00.
<% } else { %>
Sorry. You haven’t logged in.<br>
<a href=”login03.jsp”>Click here to log in.</a>
<% } %>
</body>
</html>

ในส่วนต้นของโปรแกรมนี้เป็นการตรวจสอบดูว่ามีตัวเก็บข้อมูลของ session ที่ชื่อ
isLoggedin อยู่หรือไม่ ถ้ามี ให้รับค่าของมันมาใส่ไว้ในตัวแปรสตริงชื่อเดียวกัน จากนั้นทำ
การตรวจสอบดูว่ามีค่าเป็น yes หรือไม่ ถ้าใช่ก็ให้แสดงเวบเพจหน้านั้น แต่ถ้าไม่ ก็ให้เตือน
ผู้เยี่ยมชมว่ายังไม่ได้ล็อกอินแทน
ลองสร้างไฟล์ชื่อ login03.jsp ขึ้นมาโดยมีเนื้อหาเหมือนโปรแกรมที่ 8-1 แต่เปลี่ยนพารา
มิเตอร์ action ให้มีค่าเป็น auth03.jsp ดังนี้

<% String username = new String();
String password = new String();
%>
<html>
<title>Login</title>
<body>
<form method="post" action="auth03.jsp">
Username : <input type="text" name="username" value="<%=username%>"><br>
Password : <input type="password"
name="password"value="<%=password%>"><br>
<input type="submit">
</form>
</body>
</html>

ลองใส่ชื่อ Songkarn และรหัสลับ 12345 ลงไปแล้วคลิก Submit Query มันจะเรียกไฟล์
auth03.jsp มาตอบสนอง

ตอนนี้ session ได้สร้างและเก็บ isLoggedin ที่มีค่าเท่ากับ yes ไว้แล้ว ให้ลองทดสอบโดย
การเรียกไฟล์ sample01.jsp จะได้ผลดังนี้

แต่ถ้าลองปิดเบราเซอร์แล้วเปิดใหม่ แล้วเรียกไฟล์ sample01.jsp อีกที คราวนี้จะพบว่าเข้า
ไม่ได้แล้ว เพราะ isLoggedin ตัวที่มีอยู่ตายไปพร้อมกับการปิดเบราเซอร์ ผู้เยี่ยมชมต้องทำ
การล็อกอินใหม่
แน่นอนระบบล็อกอินจริงๆ มีความซับซ้อนกว่านี้ นี่เป็นเพียงตัวอย่างเพื่อให้เข้าใจว่าเราจะ
ใช้ session จดจำข้อมูลได้อย่างไรเท่านั้น

คุ๊กกี้

คุณคงเคยใช้บริการฟรีหลายๆ อย่างบนอินเตอร์เนต เช่น อีเมล์ หรือฟรีโฮมเพจต่างๆ หรือ
ไม่ก็เคยซื้อหนังสือบนอินเตอร์เนต คุณอาจแปลกใจที่พบว่าเวบไซต์เหล่านั้นสามารถจดจำ
ชื่อ อีเมล์แอดเดรส หรือพาสเวิร์ดของคุณได้ แม้ว่าคุณจะไม่ได้เยี่ยมชมเวบไซต์เหล่านั้นมา
หลายเดือนแล้ว เวบไซต์พวกนี้อาศัยการบันทึกข้อมูลเกี่ยวกับตัวคุณไว้ในไฟล์ขนาดจิ๋วซึ่ง
มันแอบหยอดทิ้งไว้ในฮาร์ดดิสก์ของคุณเวลาที่เข้าเยี่ยมชมเวบไซต์โดยที่คุณไม่รู้ตัว เวลาที่
คุณกลับมาที่เวบไซต์เหล่านี้อีกครั้ง มันจะอ่านไฟล์ที่มันหยอดเอาไว้เพื่อดึงข้อมูลเกี่ยวกับตัว
คุณกลับมา เราเรียกไฟล์ขนาดจิ๋วเหล่านี้ว่า คุ๊กกี้

Cookie
คุ๊กกี้เป็นวัตถุบนเจเอสพี คลาสที่นิยามคุ๊กกี้ได้แก่คลาส Cookie ซึ่งมีวิธีการตั้งชื่อคุ๊กกี้และ
กำหนดค่าให้กับคุ๊กกี้ด้วยการประกาศวัตถุของคลาสคุ๊กกี้ ตัวอย่างเช่น
Cookie cookie = new Cookie(“name”, “Songkarn”);
เป็นการประกาศวัตถุชื่อ cookie ของคลาส Cookie โดยให้คุ๊กกี้นี้มีชื่อเรียกว่า name และมี
ค่าเท่ากับ Songkarnเวลาเราจะหยอดคุ๊กกี้ลงบนเบราเซอร์ของผู้เยี่ยมชม เราอาศัยแมธธอสของวัตถุแฝง
response ชื่อ addCookie() ซึ่งจะทำให้เบราเซอร์สร้างไฟล์คุ๊กกี้ที่เก็บค่าของคุ๊กกี้เอาไว้บน
ฮาร์ดดิสก์ของผู้เยี่ยมชม แต่ก่อนจะหยอดคุ๊กกี้จำเป็นที่จะต้องกำหนดวันหมดอายุของคุ๊กกี้
ก่อน คุ๊กกี้ทุกอันที่เราหยอดจะมีวันหมดอายุของมันอยู่เพื่อมิให้ข้อมูลในคุ๊กกี้เก่าเกินไป อายุ
ของคุ๊กกี้นับเป็นวินาทีนับจากวินาทีที่หยอดคุ๊กกี้ และเราใช้แมธธอส setMaxAge() ของ
คลาส Cookie ในการกำหนดวันหมดอายุ เช่น
cookie.setMaxAge(60*60*24*30);
เป็นการกำหนดให้คุ๊กกี้ที่ชื่อ cookie มีอายุ 30 วันนับจากวันที่หยอด
ตัวอย่างง่ายๆ สมมติว่าเวบไซต์ของคุณมีระบบสมาชิก ซึ่งทุกครั้งที่ผู้เยี่ยมชมเข้ามาในเวบ
ไซต์จะต้องระบุชื่อสมาชิกและรหัสผ่าน ถ้าผู้เยี่ยมชมเข้ามาทุกวันวันละหลายหน บางทีผู้
เยี่ยมชมอาจรู้สึกรำคาญที่ต้องคอยกรอกชื่อสมาชิกอยู่ตลอดเวลา เราจะลองแก้ปัญหานี้ด้วย
การใช้คุ๊กกี้ในการจดจำชื่อสมาชิกในการกรอกรหัสผ่านครั้งแรกของผู้เยี่ยมชม เพื่อที่ในการ
เยี่ยมชมครั้งต่อไปจะมีชื่อสมาชิกและรหัสเก่าโผล่ออกมารอไว้เลย ผู้เยี่ยมชมเพียงแต่กดปุ่ม
ยืนยันอย่างเดียวก็พอ
เริ่มด้วยการสร้างแบบฟอร์มระบบสมาชิกก่อน

<html>
<title>Login</title>
<body>
<form method=”post” action=”auth01.jsp”>
Username : <input type=”text” name=”username”><br>
Password : <input type=”password” name=”password”><br>
<input type=”submit”>
</form>
</body>
</html>

จากนั้นก็สร้างไฟล์ auth01.jsp ขึ้นมารับมือ ลองดูแบบที่ยังไม่มีคุ๊กกี้ก่อนเพื่อความเข้าใจ

<% String username = request.getParameter(“username”);
String password = request.getParameter(“password”);
%>
<html>
<title>Login</title>
<body>
<% if (username.equals(“Songkarn”)&&password.equals(“12345”)) { %>
Login successful.
<% } else { %>
Login failed.
<% } %>
</body>
</html>

โปรแกรมนี้รับค่า username และ password จากฟอร์มมาเปรียบเทียบ ถ้าชื่อสมาชิกคือ
songkarn และ รหัสผ่านคือ 12345 มันจะแสดงข้อความว่าล็อกอินสำเร็จ มิฉะนั้นจะแสดงข้อ
ความว่าการล็อกอินล้มเหลว (ระบบสมาชิกจริงๆ ซับซ้อนกว่านี้มาก แต่เรายังไม่ขอลงราย
ละเอียด เพราะบทนี้เราสนใจแต่เรื่องการทำคุ๊กกี้)

ที่นี้เราจะเติมคุ๊กกี้ลงไปเพื่อให้ระบบสมาชิกจดจำชื่อสมาชิกที่เคยล็อกอินได้ด้วย เริ่มจากการ
หยอดคุ๊กกี้ก่อนดังนี้

<% String username = request.getParameter("username");
String password = request.getParameter("password");
Cookie cookie = new Cookie("username",username);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
cookie = new Cookie("password",password);
cookie.setMaxAge(60*60*24*30);
response.addCookie(cookie);
%>
<html>
<title>Login</title>
<body>
<% if (username.equals("Songkarn")&&password.equals("12345")) { %>
Login successful.
<% } else { %>
Login failed.
<% } %>
</body>
</html>

โปรแกรมนี้แทนที่จะรับข้อมูลจากฟอร์มมาเฉยๆ ก็จดใส่คุ๊กกี้ลงไปด้วย คุ๊กกี้ทั้งสองตัวจะมี
อายุอยู่บนเครื่องคอมพิวเตอร์ของนายสงกรานต์เป็นเวลา 30 วัน
คราวนี้ก็มาแก้ฟอร์มสมาชิกใหม่ให้มองหาคุ๊กกี้ในเครื่องคอมพิวเตอร์ก่อน ถ้าพบคุ๊กกี้ที่มีชื่อ
ว่า username และ password ก็ให้นำมากรอกไว้ในแบบฟอร์มรอไว้ให้เลย ดังนี้

<% String username = new String();
String password = new String();
Cookie[] cookies;
Cookie cookie;
cookies = request.getCookies();
if (cookies!=null) {
for (int i = 0; i < cookies.length; i++) {
cookie = cookies[i];
if ("username".equals(cookie.getName())) {
username = cookie.getValue();
}
if ("password".equals(cookie.getName())) {
password = cookie.getValue();
}
}
}
%>
<html>
<title>Login</title>
<body>
<form method="post" action="auth02.jsp">
Username : <input type="text" name="username" value="<%=username%>"><br>
Password : <input type="password"
name="password"value="<%=password%>"><br>
<input type="submit">
</form>
</body>
</html>

วัตถุแฝง request มีแมธธอสชื่อ getCookies() ซึ่งจะคืนค่าของคุ๊กกี้ทุกตัวในฮาร์ดดิสก์ของผู้
เยี่ยมชมมาให้ในรูปของอะเรย์ Cookies[ ] หน้าที่ของเราก็คือตรวจสอบดูว่ามีคุ๊กกี้ตัวไหน
บ้างที่มีชื่อว่า username หรือ password ถ้าพบก็ให้นำค่าของมันมากำหนดค่าให้กับ ตัว
แปรสตริงที่เราสร้างขึ้นมาชื่อว่า username และ password แมธธอสที่ใช้ในการอ่านชื่อและ
ค่าของคุ๊กกี้ได้แก่ getName() และ getValue() ตามลำดับ เมื่อได้ค่าของ username และ
password ซึ่งเหมือนกับชื่อสมาชิกและรหัสผ่านที่เคยใช้แล้ว เราก็นำค่าของมันมากำหนดให้
เป็นค่าปกติของฟอร์มด้วยการกำหนดให้กับพารามิเตอร์ value เช่นนี้แล้ว หากผู้เยี่ยมชม
กลับเข้ามาตอบคำถามในหน้าเดิมอีก ชื่อเก่าของผู้เยี่ยมชมจะปรากฏขึ้นเองในช่องของชื่อผู้
ตอบคำถาม ทำให้ผู้เยี่ยมชมไม่ต้องเสียเวลากรอกชื่อสมาชิกและรหัสซ้ำอีก


สิ่งที่ควรทราบเกี่ยวกับคุ๊กกี้ก็คือ เวลาเบราเซอร์เก็บคุ๊กกี้ไว้ในฮาร์ดดิสก์มันจะแยกคุ๊กกี้ที่มา
จากเวบไซต์ต่างเวบไซต์ออกจากกันโดยเด็ดขาด นั้นคือคุ๊กกี้ที่มีชื่อซ้ำกันแต่เกิดจากคนละ
เวบไซต์จะไม่ปะปนกัน และเบราเซอร์จะยอมให้เวบไซต์ที่หยดคุ๊กกี้นั้นๆ เท่านั้นเป็นผู้อ่าน
คุ๊กกี้ ไม่มีการใช้งานข้ามเวบไซต์เป็นอันขาด นอกจากนี้เบราเซอร์ยังถือว่าคุ๊กกี้ชื่อเดียวกันที่
มาจากเวบไซต์เดียวกันแต่เวบเพจที่หยอดคุ๊กกี้เป็นคนละโฟลเดอร์ เป็นคุ๊กกี้คนละตัวกัน