{
    "mode": "perldoc",
    "parameter": "CGI::Session::Tutorial",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/perldoc/CGI%3A%3ASession%3A%3ATutorial/json",
    "generated": "2026-06-12T22:11:55Z",
    "sections": {
        "NAME": {
            "content": "CGI::Session::Tutorial - Extended CGI::Session manual\n",
            "subsections": []
        },
        "STATE MAINTENANCE OVERVIEW": {
            "content": "Since HTTP is a stateless protocol, each subsequent click to a web site is treated as new\nrequest by the Web server. The server does not relate a visit with a previous one, thus all the\nstate information from the previous requests are lost. This makes creating such applications as\nshopping carts, web sites requiring users to authenticate, impossible. So people had to do\nsomething about this despair situation HTTP was putting us in.\n\nFor our rescue come such technologies as *HTTP Cookies* and *QUERYSTRING*s that help us save\nthe users' session for a certain period. Since *HTTP Cookies* and *QUERYSTRING*s alone cannot\ntake us too far (RFC 2965, Section 5, \"Implementation Limitations\"), several other libraries\nhave been developed to extend their capabilities and promise a more reliable solution.\nCGI::Session is one of them.\n\nBefore we discuss this library, let's look at some alternative solutions.\n\nCOOKIE\nCookie is a piece of text-information that a web server is entitled to place in the user's hard\ndisk, assuming a user agent (such as Internet Explorer, Mozilla, etc) is compatible with the\nspecification. After the cookie is placed, user agents are required to send these cookies back\nto the server as part of the HTTP request. This way the server application ( CGI, for example )\nwill have a way of relating previous requests by the same user agent, thus overcoming\nstatelessness of HTTP.\n\nAlthough *HTTP Cookies* seem to be promising solution for the statelessness of HTTP, they do\ncarry certain limitations, such as limited number of cookies per domain and per user agent and\nlimited size on each cookie. User Agents are required to store at least 300 cookies at a time,\n20 cookies per domain and allow 4096 bytes of storage for each cookie. They also rise several\nPrivacy and Security concerns, the lists of which can be found on the sections 6-\"Privacy\" and\n7-\"Security Considerations\" of RFC 2965.\n\nQUERY STRING\nQuery string is a string appended to URL following a question mark (?) such as:\n\nhttp://my.dot.com/login.cgi?user=sherzodr;password=top-secret\n\nAs you probably guessed, it can also help you pass state information from a click to another,\nbut how secure is it do you think, considering these URLs tend to get cached by most of the user\nagents and also logged in the servers access log, to which everyone can have access.\n\nHIDDEN FIELDS\nHidden field is another alternative to using query strings and they come in two flavors: hidden\nfields used in POST methods and the ones in GET. The ones used in GET methods will turn into a\ntrue query strings once submitted, so all the disadvantages of QUERYSTRINGs apply. Although\nPOST requests do not have limitations of its sister-GET, the pages that hold them get cached by\nWeb browser, and are available within the source code of the page (obviously). They also become\nunwieldily to manage when one has oodles of state information to keep track of ( for instance, a\nshopping cart or an advanced search engine).\n\nQuery strings and hidden fields are also lost easily by closing the browser, or by clicking the\nbrowser's \"Back\" button.\n\nSERVER SIDE SESSION MANAGEMENT\nThis technique is built upon the aforementioned technologies plus a server-side storage device,\nwhich saves the state data on the server side. Each session has a unique id associated with the\ndata in the server. This id is also associated with the user agent either in the form of a *HTTP\nCookie*, a *QUERYSTRING*, hidden field or any combination of the above. This is necessary to\nmake the connection with the client and his data.\n\nAdvantages:\n\n*   We no longer need to depend on User Agent constraints in cookie size.\n\n*   Sensitive data no longer need to be traveling across the network at each request (which is\nthe case with query strings, cookies and hidden fields). The only thing that travels is the\nunique id generated for the session (5767393932698093d0b75ef614376314, for instance), which\nshould make no sense to third parties.\n\n*   User will not have sensitive data stored in his/her computer in unsecured file (which is a\ncookie file).\n\n*   It's possible to handle very big and even complex data structures transparently (which *HTTP\nCookies* do not handle).\n\nThat's what CGI::Session is all about - implementing server side session management. Now is a\ngood time to get feet wet.\n",
            "subsections": []
        },
        "PROGRAMMING STYLE": {
            "content": "Server side session management system might be seeming awfully convoluted if you have never\ndealt with it. Fortunately, with CGI::Session all the complexity is handled by the library\ntransparently. This section of the manual can be treated as an introductory tutorial to both\nlogic behind session management, and to CGI::Session programming style.\n\nAll applications making use of server side session management rely on the following pattern of\noperation regardless of the way the system is implemented:\n\n1   Check if the user has session cookie dropped in his computer from previous request\n\n2   If the cookie does not exist, create a new session identifier, and drop it as cookie to the\nuser's computer.\n\n3   If session cookie exists, read the session ID from the cookie and load any previously saved\nsession data from the server side storage. If session had any expiration date set it's\nuseful to re-drop the same cookie to the user's computer so its expiration time will be\nreset to be relative to user's last activity time.\n\n4   Store any necessary data in the session that you want to make available for the next HTTP\nrequest.\n\nCGI::Session will handle all of the above steps. All you have to do is to choose what to store\nin the session.\n\nGETTING STARTED\nTo make CGI::Session's functionality available in your program do either of the following\nsomewhere on top of your program file:\n\nuse CGI::Session;\n# or\nrequire CGI::Session;\n\nWhenever you're ready to create a new session in your application, do the following:\n\n$session = CGI::Session->new () or die CGI::Session->errstr;\n\nAbove line will first try to re-initialize an existing session by consulting cookies and\nnecessary QUERYSTRING parameters. If it fails will create a brand new session with a unique ID,\nwhich is normally called *session ID*, *SID* for short, and can be accessed through id() -\nobject method.\n\nWe didn't check for any session cookies above, did we? No, we didn't, but CGI::Session did. It\nlooked for a cookie called \"CGISESSID\", and if it found it tried to load existing session from\nserver side storage (file in our case). If cookie didn't exist it looked for a QUERYSTRING\nparameter called \"CGISESSID\". If all the attempts to recover session ID failed, it created a new\nsession.\n\nNOTE: For the above syntax to work as intended your application needs to have write access to\nyour computer's *TEMPDIR* folder, which is usually /tmp in UNIX. If it doesn't, or if you wish\nto store this application's session files in a different place, you may pass the third argument\nlike so:\n\n$session = CGI::Session->new(undef, undef, {Directory=>'../tmp/sessions'});\n\nNow it will store all the newly created sessions in (and will attempt to initialize requested\nsessions from) that folder. Don't worry if the directory hierarchy you want to use doesn't\nalready exist. It will be created for you. For details on how session data are stored refer to\nCGI::Session::Driver::file, which is the default driver used in our above example.\n\nThere is one small, but very important thing your application needs to perform after creating\nCGI::Session object as above. It needs to drop Session ID as an *HTTP cookie* into the user's\ncomputer. CGI::Session will use this cookie to identify the user at his/her next request and\nwill be able to load his/her previously stored session data.\n\nTo make sure CGI::Session will be able to read your cookie at next request you need to consult\nits \"name()\" method for cookie's suggested name:\n\n$cookie = $query->cookie( -name   => $session->name,\n-value  => $session->id );\nprint $query->header( -cookie=>$cookie );\n\n\"name()\" returns \"CGISESSID\" by default. If you prefer a different cookie name, you can change\nit as easily too, but you have to do it before CGI::Session object is created:\n\nCGI::Session->name(\"SID\");\n$session = CGI::Session->new();\n\nBaking the cookie wasn't too difficult, was it? But there is an even easier way to send a cookie\nusing CGI::Session:\n\nprint $session->header();\n\nThe above will create the cookie using CGI::Cookie and will return proper http headers using\nCGI.pm's CGI method. Any arguments to CGI::Session will be passed to CGI::header().\n\nOf course, this method of initialization will only work if client is accepting cookies. If not\nyou would have to pass session ID in each URL of your application as QUERYSTRING. For\nCGI::Session to detect it the name of the parameter should be the same as returned by name():\n\nprintf (\"<a href=\\\"$ENV{SCRIPTNAME}?%s=%s\\\">click me</a>\", $session->name, $session->id);\n\nIf you already have session id to be initialized you may pass it as the only argument, or the\nsecond argument of multi-argument syntax:\n\n$session = CGI::Session->new( $sid );\n$session = CGI::Session->new( \"serializer:freezethaw\", $sid );\n$session = CGI::Session->new( \"driver:mysql\", $sid, {Handle=>$dbh} );\n\nBy default CGI::Session uses standard CGI to parse queries and cookies. If you prefer to use a\ndifferent, but compatible object you can pass that object in place of $sid:\n\n$cgi     = CGI::Simple->new();\n$session = CGI::Session->new( $cgi );\n$session = CGI::Session->new( \"driver:dbfile;serializer:storable\", $cgi);\n# etc\n\nSee CGI::Simple\n\nSTORING DATA\nCGI::Session offers param() method, which behaves exactly as CGI.pm's param() with identical\nsyntax. param() is used for storing data in session as well as for accessing already stored\ndata.\n\nImagine your customer submitted a login form on your Web site. You, as a good host, wanted to\nremember the guest's name, so you can a) greet him accordingly when he visits your site again,\nor b) to be helpful by filling out *user name* part of his login form, so the customer can jump\nright to the *password* field without having to type his username again.\n\nmy $name = $cgi->param('username');\n$session->param('username', $name);\n\nNotice, we're grabbing *username* value of the field using CGI.pm's (or another compatible\nlibrary's) \"param()\" method, and storing it in session using CGI::Session's param() method.\n\nIf you have too many stuff to transfer into session, you may find yourself typing the above code\nover and over again. I've done it, and believe me, it gets very boring too soon, and is also\nerror-prone. So we introduced the following handy method:\n\n$session->saveparam(['name']);\n\nIf you wanted to store multiple form fields just include them all in the second list:\n\n$session->saveparam(['name', 'email']);\n\nIf you want to store all the available *QUERYSTRING* parameters you can omit the arguments:\n\n$session->saveparam();\n\nSee saveparam() for more details.\n\nWhen storing data in the session you're not limited to strings. You can store arrays, hashes and\neven most objects. You will need to pass them as references (except objects).\n\nFor example, to get all the selected values of a scrolling list and store it in the session:\n\nmy @fruits = $cgi->param('fruits');\n$session->param('fruits', \\@fruits);\n\nFor parameters with multiple values saveparam() will do the right thing too. So the above is\nthe same as:\n\n$session->saveparam($cgi, ['fruits']);\n\nAll the updates to the session data using above methods will not reflect in the data store until\nyour application exits, or $session goes out of scope. If, for some reason, you need to commit\nthe changes to the data store before your application exits you need to call flush() method:\n\n$session->flush();\n\nI've written a lot of code, and never felt need for using \"flush()\" method, since CGI::Session\ncalls this method at the end of each request. There are, however, occasions I can think of one\nmay need to call flush().\n\nACCESSING STORED DATA\nThere's no point of storing data if you cannot access it. You can access stored session data by\nusing the same param() method you once used to store them. Remember the Username field from the\nprevious section that we stored in the session? Let's read it back so we can partially fill the\nLogin form for the user:\n\n$name = $session->param(\"name\");\nprintf \"<input type=\\\"text\\\" name=\\\"name\\\" value=\\\"%s\\\" />\", $name;\n\nTo retrieve previously stored @fruits do not forget to de reference it:\n\n@fruits = @{ $session->param('fruits') };\n\nVery frequently, you may find yourself having to create pre-filled and pre-selected forms, like\nradio buttons, checkboxes and drop down menus according to the user's preferences or previous\naction. With text and textareas it's not a big deal - you can simply retrieve a single parameter\nfrom the session and hard code the value into the text field. But how would you do it when you\nhave a group of radio buttons, checkboxes and scrolling lists? For this purpose, CGI::Session\nprovides loadparam() method, which loads given session parameters to a CGI object (assuming\nthey have been previously saved with saveparam() or alternative):\n\n$session->loadparam($cgi, [\"fruits\"]);\n\nNow when you say:\n\nprint $cgi->checkboxgroup(fruits=>['apple', 'banana', 'apricot']);\n\nSee loadparam() for details.\n\nGenerated checkboxes will be pre-filled using previously saved information.\n\nIf you're making use of HTML::Template to separate the code from the skin, you can as well\nassociate CGI::Session object with HTML::Template and access all the parameters from within HTML\nfiles. We love this trick!\n\n$template = HTML::Template->new(filename=>\"some.tmpl\", associate=>$session);\nprint $template->output();\n\nAssuming the session object stored \"firstname\" and \"email\" parameters while being associated\nwith HTML::Template, you can access those values from within your \"some.tmpl\" file now:\n\nHello <a href=\"mailto:<TMPLVAR email>\"> <TMPLVAR firstname> </a>!\n\nSee HTML::Template's online manual for details.\n\nCLEARING SESSION DATA\nYou store session data, you access session data and at some point you will want to clear certain\nsession data, if not all. For this purpose CGI::Session provides clear() method which optionally\ntakes one argument as an arrayref indicating which session parameters should be deleted from the\nsession object:\n\n$session->clear([\"~logged-in\", \"email\"]);\n\nAbove line deletes \"~logged-in\" and \"email\" session parameters from the session. And next time\nyou say:\n\n$email = $session->param(\"email\");\n\nit returns undef. If you omit the argument to clear(), be warned that all the session parameters\nyou ever stored in the session object will get deleted. Note that it does not delete the session\nitself. Session stays open and accessible. It's just the parameters you stored in it gets\ndeleted\n\nSee clear() for details.\n\nDELETING A SESSION\nIf there's a start there's an end. If session could be created, it should be possible to delete\nit from the disk for good:\n\n$session->delete();\n\nThe above call to delete() deletes the session from the disk for good. Do not confuse it with",
            "subsections": [
                {
                    "name": "clear",
                    "content": "See delete() for details.\n\nEXPIRATION\nCGI::Session provides limited means to expire sessions. Expiring a session is the same as\ndeleting it via delete(), but deletion takes place automatically. To expire a session, you need\nto tell the library how long the session would be valid after the last access time. When that\ntime is met, CGI::Session refuses to retrieve the session. It deletes the session and returns a\nbrand new one. To assign expiration ticker for a session, use expire():\n\n$session->expire(3600);     # expire after 3600 seconds\n$session->expire('+1h');    # expire after 1 hour\n$session->expire('+15m');   # expire after 15 minutes\n$session->expire('+1M');    # expire after a month and so on.\n\nWhen session is set to expire at some time in the future, but session was not requested at or\nafter that time has passed it will remain in the disk. When expired session is requested\nCGI::Session will remove the data from disk, and will initialize a brand new session.\n\nSee expire() for details.\n\nBefore CGI::Session 4.x there was no way of intercepting requests to expired sessions.\nCGI::Session 4.x introduced new kind of constructor, load(), which is identical in use to new(),\nbut is not allowed to create sessions. It can only load them. If session is found to be expired,\nor session does not exist it will return an empty CGI::Session object. And if session is\nexpired, in addition to being empty, its status will also be set to expired. You can check\nagainst these conditions using empty() and isexpired() methods. If session was loaded\nsuccessfully object returned by \"load()\" is as good a session as the one returned by \"new()\":\n\n$session = CGI::Session->load() or die CGI::Session->errstr;\nif ( $session->isexpired ) {\ndie \"Your session expired. Please refresh your browser to re-start your session\";\n}\nif ( $session->isempty ) {\n$session = $session->new();\n}\n\nAbove example is worth an attention. Remember, all expired sessions are empty sessions, but not\nall empty sessions are expired sessions. Following this rule we have to check with\n\"isexpired()\" before checking with \"isempty()\". There is another thing about the above\nexample. Notice how its creating new session when un existing session was requested? By calling\n\"new()\" as an object method! Handy thing about that is, when you call \"new()\" on a session\nobject new object will be created using the same configuration as the previous object.\n\nFor example:\n\n$session = CGI::Session->load(\"driver:mysql;serializer:storable\", undef, {Handle=>$dbh});\nif ( $session->isexpired ) {\ndie \"Your session is expired. Please refresh your browser to re-start your session\";\n}\nif ( $session->isempty ) {\n$session = $session->new();\n}\n\nInitial $session object was configured with mysql as the driver, storable as the serializer and\n$dbh as the database handle. Calling \" new() \" on this object will return an object of the same\nconfiguration. So $session object returned from \" new() \" in the above example will use mysql as\nthe driver, storable as the serializer and $dbh as the database handle.\n\nSee isexpired(), isempty(), load() for details.\n\nSometimes it makes perfect sense to expire a certain session parameter, instead of the whole\nsession. I usually do this in my login enabled sites, where after the user logs in successfully,\nI set his/her \"loggedin\" session parameter to true, and assign an expiration ticker on that\nflag to something like 30 minutes. It means, after 30 idle minutes CGI::Session will clear\n\"loggedin\" flag, indicating the user should log in over again. I agree, the same effect can be\nachieved by simply expiring() the session itself, but by doing this we would loose other session\nparameters, such as user's shopping cart, session-preferences and the like.\n\nThis feature can also be used to simulate layered authentication, such as, you can keep the\nuser's access to his/her personal profile information for as long as 60 minutes after a\nsuccessful login, but expire his/her access to his credit card information after 5 idle minutes.\nTo achieve this effect, we will use expire() method again:\n\n$session->expire(profileaccess, '1h');\n$session->expire(ccaccess, '5m');\n\nWith the above syntax, the person will still have access to his personal information even after\n5 idle hours. But when he tries to access or update his/her credit card information, he may be\ndisplayed a \"login again, please\" screen.\n\nSee expire() for details.\n\nThis concludes our discussion of CGI::Session programming style. The rest of the manual covers\nsome \"SECURITY\" issues. Driver specs from the previous manual were moved to\nCGI::Session::Driver.\n"
                }
            ]
        },
        "SECURITY": {
            "content": "\"How secure is using CGI::Session?\", \"Can others hack down people's sessions using another\nbrowser if they can get the session id of the user?\", \"Are the session ids easy to guess?\" are\nthe questions I find myself answering over and over again.\n\nSTORAGE\nSecurity of the library does in many aspects depend on the implementation. After making use of\nthis library, you no longer have to send all the information to the user's cookie except for the\nsession id. But, you still have to store the data in the server side. So another set of\nquestions arise, can an evil person get access to session data in your server, even if he does,\ncan he make sense out of the data in the session file, and even if he can, can he reuse the\ninformation against a person who created that session. As you see, the answer depends on\nyourself who is implementing it.\n\n*   First rule of thumb, do not store users' passwords or other sensitive data in the session,\nplease. If you have to, use one-way encryption, such as md5, or SHA-1-1. For my own\nexperience I can assure you that in properly implemented session-powered Web applications\nthere is never a need for it.\n\n*   Default configuration of the driver makes use of Data::Dumper class to serialize data to\nmake it possible to save it in the disk. Data::Dumper's result is a human readable data\nstructure, which, if opened, can be interpreted easily. If you configure your session object\nto use either Storable or FreezeThaw as a serializer, this would make it more difficult for\nbad guys to make sense out of session data. But don't use this as the only precaution. Since\nevil fingers can type a quick program using Storable or FreezeThaw to decipher session files\nvery easily.\n\n*   Do not allow anyone to update contents of session files. If you're using default serializer\nserialized data string needs to be eval()ed to bring the original data structure back to\nlife. Of course, we use Safe to do it safely, but your cautiousness does no harm either.\n\n*   Do not keep sessions open for very long. This will increase the possibility that some bad\nguy may have someone's valid session id at a given time (acquired somehow). To do this use\nexpire() method to set expiration ticker. The more sensitive the information on your Web\nsite is, the sooner the session should be set to expire.\n\nSESSION IDs\nSession ids are not easily guessed (unless you're using incr ID generator)! Default\nconfiguration of CGI::Session uses Digest::MD5 to generate random, 32 character long identifier.\nAlthough this string cannot be guessed as easily by others, if they find it out somehow, can\nthey use this identifier against the other person?\n\nConsider the scenario, where you just give someone either via email or an instant messaging a\nlink to a Web site where you're currently logged in. The URL you give to that person contains a\nsession id as part of a query string. If the site was initializing the session solely using\nquery string parameter, after clicking on that link that person now appears to that site as you,\nand might have access to all of your private data instantly.\n\nEven if you're solely using cookies as the session id transporters, it's not that difficult to\nplant a cookie in the cookie file with the same id and trick the web browser to send that\nparticular session id to the server. So key for security is to check if the person who's asking\nus to retrieve a session data is indeed the person who initially created the session data.\n\nOne way to help with this is by also checking that the IP address that the session is being used\nfrom is always same. However, this turns out not to be practical in common cases because some\nlarge ISPs (such as AOL) use proxies which cause each and every request from the same user to\ncome from different IP address.\n\nIf you have an application where you are sure your users' IPs are constant during a session, you\ncan consider enabling an option to make this check:\n\nuse CGI::Session '-ipmatch';\n\nFor backwards compatibility, you can also achieve this by setting $CGI::Session::IPMATCH to a\ntrue value. This makes sure that before initializing a previously stored session, it checks if\nthe ip address stored in the session matches the ip address of the user asking for that session.\nIn which case the library returns the session, otherwise it dies with a proper error message.\n",
            "subsections": []
        },
        "LICENSING": {
            "content": "For support and licensing see CGI::Session\n",
            "subsections": []
        }
    },
    "summary": "CGI::Session::Tutorial - Extended CGI::Session manual",
    "flags": [],
    "examples": [],
    "see_also": []
}