Abstract
Html 5 offers us with Web Storage features. Developer can make their application as per the requirements. The term Web Storage defines the set of browser capability to allow application level persistent storage of key/value pairs on the client side. In this article we will be focusing on HTML5 Web Storage API: Session Storage and Local Storage attributes and will create a small MVC app by the help of Session Storage.
Introduction
Web Storage is the process of storing the structured data in the client Web browser with the help of JavaScript. The storage mechanism is implemented via key/value. It is exposed to us via two global objects called localStorage and sessionStorage. We can use these objects to what data to be stored, updated or deleted when needed. Web storage works extensively with client side scripting language where data can be transferred to the server on requirement and server can’t alter the data to the web storage.
Local Storage
Local storage is useful when you want to save the data to be accessible across multiple browser windows and keep the data long for persistent days even after the browser is closed and reopened.
Example 1: Usage of Local Storage
Code Snippet
- $('#btnLocalStorage').click(function()
- {
- var txtName = $("#txtName").val();
-
- localStorage.setItem("EmpName", txtName);
- });
-
- $('#btnLocalStorageRemove').click(function()
- {
-
- localStorage.removeItem("EmpName");
- });
- $('#btnLocalStorageClear').click(function()
- {
-
- localStorage.clear();
- });
- $('#btnLocalStorageLength').click(function()
- {
- var localStoragelength = localStorage.length;
- alert("The length of Local storage is " + localStoragelength);
-
- });
Demonstrating we insert the item by defining key and data.
Demonstrating the local storage set item, with stored data.
Your keys and values must be string. We have to rely upon toString() and JSON.stringify(converting JavaScript value to a JSON string), JSON.parse (to convert JSON text into JavaScript object).
Let’s take a small demo of storing the values in the Local Storage using Visual Studio. Here I will simply store the data to the local storage. As discussed earlier the data is saved in the local storage with a Key and its respective value. Let’s get started:
//Code snippet
Simple UI
Demonstrating the Simple UI screen.
Let’s start debugging our application.
Phase 1
Demonstrating the debug point and local storage.
Phase 2
Demonstrating: As there is no key with name user a new array is created and user information is pushed to UserArray.
Phase 3
Demonstrating the local storage has been set with key named users and all the object properties has been set to the Key as shown above at right hand side.
Phase 4
Demonstrating all the records present in key users is being stored in collection of user in the form of JavaScript objects as shown above.
Phase 5
Demonstrating moving object one by one and displayed to the table
Phase 6
Demonstrating User Interface after function execution.
Benefits of Local Storage
- Saving program state, or saving some information that is needed across the entire web application.
- Local storage gives limit of 5MB of data to be stored on client side.
- It stores data with no expiration date, and gets cleared only using JavaScript, or clearing the Browser Cache / Locally Stored Data.
Session Storage:
Everything you saw above in localStorage object also applies to the sessionStorage as well. The way you additem, removeitem is same as in LocalStorage, the only difference is the syntax name. The major difference between session storage and local storage is data persistence. Which means when we use localStorage data is present and available across various sessions (across multiple window) i.e. you can close your browser and come later and any data that has been stored in localStorage will be available to you. While in Session Storage the data is used only on one browser window which means as soon as we close our window our session keys are destroyed and will not be accessible across sessions. It allows separate instance of application run in different windows without affecting each other. The values of session storage remains persistent after page load also.
Example 2: Usage of Session Storage
Code Snippet
- $('#btnSessionStorage').click(function()
- {
- debugger;
- var txtName = $("#txtName").val();
-
- sessionStorage.setItem("EmpName", txtName);
-
- });
-
- $('#btnSessionStorageRemove').click(function()
- {
- debugger;
-
-
- sessionStorage.removeItem("EmpName");
- });
- $('#btnSessionStorageClear').click(function()
- {
- debugger;
-
-
- sessionStorage.clear();
-
- });
Demonstrating the session storage length attribute.
We will be creating a simple Meeting application using Local storage as we go ahead, before that lets discuss the most mind oscillating topic called Security.
With the origin of Cookies as the HTTP state management website stores cookies as to relate HTTP requests to each other. With the help of cookies the simple HTTP stateless protocol becomes stateful.
Benefits of Web Storage
- Based on the Html UI survey we can see that the Web storage is utilized frequently to locally stored code fragments probably for catching and fast responsiveness.
- Easy to use API, with simple get and set key/value pairs.
- Huge amount of data storage space.
Drawback of Web Storage
- Data is stored without any encryption on disk. i.e. anyone who has access to the system can get access to the data.
- In localStorage if until the website delete the data or user explicitly clear the data by telling the browser i.e. the data will be persistent for lifetime.
Security Concerns
As all the local storage is saved in client side, it can be tempered or can be seen by anyone who has sound knowledge of browser working and web. Just type localStorage in console window or go to resource and there they are.
Local storage is a threat when a browser is being shared by the multiple users example like cyber cafe, where any person can inject malicious script that can steal the user assets.
Let’s start and create a normal meeting scheduling app in Visual studio using ASP.NET MVC and session storage.
Create Simple Model classes as shown below:
Let’s create our View, just a gentle reminder I will be using session storage for storage of data on the client browser and when all the information is gathered same will be inserted into the db.
UI
- @ {
- Layout = null;
- }
-
- < !DOCTYPEhtml >
-
- < html >
- < head >
- < meta name = "viewport"
- content = "width=device-width" / >
- < title > Index < /title> < style >
-
-
- .ui - datepicker - current - day.ui - state - active {
- background: #0094ff; }
- div.ui-datepicker
- {
- font-size: 12px;
-
-
- color: # f00;
-
- } < /style> < scriptsrc = "~/Scripts/jquery-1.10.2.js" > < /script> < scriptsrc = "~/Scripts/jquery.dateFormat-1.0.js" > < /script> < scriptsrc = "~/Scripts/jquery-ui-1.11.4.js" > < /script> < linkhref = "~/Content/jquery-ui-1.10.4.custom.css"
- rel = "stylesheet" / >
- < script >
-
- $(function()
- {
-
- $(".date-picker").datepicker({
- dateFormat: 'dd-mm-yy'
- });
-
- });
-
- $(document).ready(function()
- {
-
-
- $("#showMessage").dialog({
- modal: true,
- closeOnEscape: false,
- open: function(event, ui)
- {
- $(".ui-dialog-titlebar-close", ui.dialog || ui).hide();
- },
- buttons: {
- Ok: function()
- {
-
- $(this).dialog("close");
- }
- }
- });
-
-
- $('#btnAdd').click(function()
- {
- $('#UserInfo').empty();
-
-
-
-
- var participant = new Object();
-
- participant.participantName = btoa($('#txtName').val());
- participant.participantEmail = btoa($('#txtEmail').val());
-
- if (sessionStorage.Participants)
- {
-
-
- Participants = JSON.parse(sessionStorage.getItem('Participants'));
-
- } else
- {
-
- Participants = [];
- }
-
- Participants.push(participant);
- sessionStorage.setItem('Participants', JSON.stringify(Participants));
-
- var ListToShow = JSON.parse(sessionStorage.getItem("Participants"));
-
- $('#UserInfo').show();
- var header = "<tr><th style='text-align:left'>User Name</th><th colspan='2' style='text-align:left'>Email</th></tr>";
- $('#UserInfo').append(header);
- $.map(ListToShow, function(UserDetails)
- {
-
-
- var Userinfo = "<tr><td >" + atob(UserDetails.participantName) + "</td><td colspan='2'>" + atob(UserDetails.participantEmail) + "</td></tr>";
-
-
- $('#UserInfo').append(Userinfo);
- });
- $('#txtName').val("")
- $('#txtEmail').val("")
-
- });
-
- $('#BtnSubmit').click(function()
- {
-
-
-
- var mtngDate1 = new Object();
- mtngDate1.StartTime = $('#txtStartTime').val();
- mtngDate1.EndTime = $('#txtEndTime').val();
- mtngDate1.DateOfMeeting = $('#Date_Of_Meeting').val();
-
-
- var agenda = new Object();
- agenda.AgendaName = $('#txtMtngAgenda').val();
-
-
- var mtng = new Object();
- mtng.MtngName = $('#txtMtngNAME').val();
-
- var participantsDetails = JSON.parse(sessionStorage.getItem('Participants'));
- participantsDetailas = JSON.stringify({
- 'participantsDetails': participantsDetails,
- 'mtngDate': mtngDate1,
- 'agendaCovered': agenda,
- 'mtngNameCovered': mtng
- });
- $.ajax({
- type: 'POST',
- traditional: true,
- dataType: "json",
- url: '/Test/CreateMtng',
- contentType: "application/json; charset=utf-8",
- data: participantsDetailas,
- success: function(data)
- {
-
- alert(data);
- sessionStorage.clear();
- $('#txtMtngNAME').val("");
- $('#txtMtngAgenda').val("");
- $('#Date_Of_Meeting').val("");
- $('#txtStartTime').val("");
- $('#txtEndTime').val("");
- $('#UserInfo').empty();
- },
- error: function()
- {
- alert('failure');
- }
- })
-
- });
- }); < /script>
-
- < /head> < body >
- < div >
- < tablealign = "center"
- frame = "box" >
- < tr >
-
- < thcolspan = "3" > Meeting Scheduler < /th> < /tr> < tr >
- < thstyle = "text-align:left" > Meeting Name < /th> < td > < inputid = "txtMtngNAME"
- name = "Meeting.MtngName"
- type = "text" / > < /td> < /tr> < tr >
-
- < thstyle = "text-align:left" > Agenda Covered < /th> < td > < inputid = "txtMtngAgenda"
- name = "Agenda.AgendaName"
- type = "text" / > < /td> < /tr> < tr >
- < thstyle = "text-align:left" > Date of Meeting < /th> < td >
- @Html.TextBox("Date Of Meeting", "---- Target Date----", new {
- placeholder = "Enter Date", style = " text-align:left", autocomplete = "off", @class = "date-picker", name = "Date.DateOfMeeting"
- }) < /td>
-
-
- < /tr> < tr >
- < thcolspan = "2"
- style = "text-align:left" > Participants Details < /th> < /tr> < tr >
- < td > < inputid = "txtName"
- type = "text"
- placeholder = "Enter CustomerName" / > < /td> < td > < inputid = "txtEmail"
- type = "text"
- placeholder = "Enter Email id" / > < /td> < td > < inputid = "btnAdd"
- type = "button"
- value = "Add Participants" / > < /td>
-
-
- < /tr> < tr >
- < tdstyle = "text-align:left" >
-
- Participants
-
- < /td> < /tr> < tr >
- < tdcolspan = "3" >
- < tableid = "UserInfo"
- style = "width:100%;"
- align = "center"
- frame = "box" >
-
-
-
- < /table>
-
-
- < /td>
-
- < /tr> < tr >
- < thstyle = "text-align:left" > Start time < /th> < td > < inputid = "txtStartTime"
- type = "text"
- name = "Date.StartTime" / > < /td>
-
- < /tr> < tr >
- < thstyle = "text-align:left" > EndTime time < /th> < td > < inputid = "txtEndTime"
- type = "text"
- name = "Date.EndTime" / > < /td>
-
- < /tr> < tr >
- < tdcolspan = "3"
- style = "text-align:center" > < inputid = "BtnSubmit"
- type = "button"
- value = "Create Meeting" / > < /td> < /tr> < /table> < /div> < /body> < /html>
-
-
-
- Create a Controller
-
- public class TestController: Controller
- {
-
- public ActionResult Index()
- {
- return View();
- }
-
-
- public ActionResult CreateMtng(MeetingVM objVm)
- {
-
-
- DAL objDal = newDAL();
-
-
- MeetingMaster mtngMasterDetails = newMeetingMaster();
-
- mtngMasterDetails.Name = objVm.mtngNameCovered.MtngName.ToString();
- mtngMasterDetails.Agenda_Covered = objVm.agendaCovered.AgendaName.ToString().Trim();
- mtngMasterDetails.Date_Of_Meeting = objVm.mtngDate.DateOfMeeting.ToString().Trim();
- mtngMasterDetails.End_Time = objVm.mtngDate.EndTime.ToString().Trim();
- mtngMasterDetails.Start_Time = objVm.mtngDate.StartTime.ToString().Trim();
-
-
-
- objDal.mtngMaster.Add(mtngMasterDetails);
-
-
- objDal.SaveChanges();
-
- int MtngId = mtngMasterDetails.ID;
-
-
-
- Participants participant = newParticipants();
- foreach(Employee obj in objVm.participantsDetails)
- {
-
- participant.MomId = MtngId;
-
- byte[] dataEmail = Convert.FromBase64String(obj.participantEmail);
- byte[] dataName = Convert.FromBase64String(obj.participantName);
- string decodedEmail = Encoding.UTF8.GetString(dataEmail);
- string decodedName = Encoding.UTF8.GetString(dataName);
- participant.Email = decodedEmail;
- participant.Name = obj.participantName;
-
- objDal.participants.Add(participant);
- objDal.SaveChanges();
- }
-
-
- string response = "The Meeting Successfully createed with id " + MtngId;
- return Json(response, JsonRequestBehavior.AllowGet);
-
- }
- }
Table for Meeting Master
ID here is an Identity column where in TblParticipants MomId is not Identity.
Table for Participants,
//DAL
We will be using Entity Framework for mapping our Models to the DB schema.
- public classDAL: DbContext
- {
-
- public DbSet < MeetingMaster > mtngMaster
- {
- get;
- set;
- }
- publicDbSet < Participants > participants
- {
- get;
- set;
- }
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
-
- modelBuilder.Entity < MeetingMaster > ().ToTable("TblMeetingMaster");
- modelBuilder.Entity < Participants > ().ToTable("TblParticipants");
- }
- }
Let’s start and debug our program step by step,
Secretary creates a list of Participants to be added and click on Add participants. Here the list of participants will be stored in session storage rather than storing it session on server side. We will encoding the value using base-64 encoded to keep the value secret. These values can be manipulated easily injecting malicious JavaScript while if the user directly changes the value it will fail to decode as it will not be 64 bit encoded. We will test the same scenario during the debugging.
Debugger Stages
Stage 1:
We can see the textbox values being encoded in 64 bit.
'sessionStorage.Participants' checks for if there is already any Participants key present in sessionStorage if not than create array of Participants and push the Participant object into the array and then save the same in sessionStorage.
Value stored in session Storage with key Participants.
As new key has been inserted in session storage, now if we check '
sessionStorage.Participants' we will receive the above output. If I try to inject the JavaScript over here and delete the key and insert a new key it can be easily done. Let’s see what happens,
I cleared session storage and tried to change the value and added encoded 64 of ‘hacker’ this may seems foolish as I am changing the value from the console window. Let’s check what value appears on the browser for participants.
As we can see the value has been manipulated, same can happen when someone inject malicious script and change the data, so it’s strictly said not to store important credentials and users important information in localStorage or sessionStorage as it’s vulnerable to attacks easily.
Let’s focus and create a Meeting app using ASP.NET MVC.
Secretary has inserted the details and creates the meeting.
We create object of all the details to be passed to the Controller, as we know before passing the objects we need to Stringfy the objects as shown below,
Hits comes to the Controllers,
All the values passed from the View to the Controller, and participants values are encoded in 64 bit.
Decoding of Participants name and email.
Meeting has been successfully created with id 1.
Successful creation of meeting.
Let’s check the database values,
You can add mailing features also, so that all the participants will receive the mail regarding minutes of the Meeting.
Hence I conclude that Web Storage is a really amazing concept with drawbacks as well. I was unaware of Web Storage features before this so I wanted to unleash this topic from scratch. I hope this article will be helpful to everyone. I would be happy and will feel appreciated if you could comment and improvise me in doing better and learning the security measures to be taken while using sessionStorage or LocalStorage.