{ "info": { "author": "Zope Corporation", "author_email": "info@zope.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Paste", "Framework :: Zope3", "Intended Audience :: Developers", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI", "Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "****************\nZC WSGI Sessions\n****************\n\nThis is an implementation of persistent sessions as a WSGI middleware\nusing `zope.session` as an underlying mechanism.\n\nTo use it:\n\n1. Add `zc.wsgisessions` to `install_requires` list in `setup.py` of\n your application (e.g., `myapp`)\n\n2. Add the following to `myapp.ini`::\n\n [filter:sessions]\n use = egg:zc.wsgisessions\n\n You can add to configuration::\n\n secure = true\n\n or::\n\n http-only = off\n\n Valid words are: `true`, `false`, `on`, `off`, `yes`, `no`, 1, and 0.\n\n Other options include::\n\n domain = .example.com\n\n max-age = 10000\n\n path = /foo\n\n You can also specify a database name for session storage::\n\n db-name = appdb\n\n3. Add `sessions` to the pipeline *after* database middleware, but\n *before* the application.\n\n4. Add to a function that is listed as `initializer` for the database\n middleware::\n\n zc.wsgisessions.sessions.initialize_database(database)\n\n You can also pass keyword arguments for: `db_name`, `namespace`,\n `secret`, `timeout`, and `resolution`.\n\n5. Add to a function that is listed as `bobo.configure` (initializer of\n your WSGI application)::\n\n zope.component.provideAdapter(zc.wsgisessions.sessions.get_session)\n\n6. You can use some helpers in your authentication code::\n\n PKG_KEY = __name__ # e.g., myapp.auth\n\n def get_user(request):\n return zc.wsgisessions.sessions.get(request, PKG_KEY, 'user')\n\n def save_user(request, user):\n zc.wsgisession.sessions.store(request, PKG_KEY, 'user', user)\n\n def forget_user(request):\n return zc.wsgisessions.sessions.remove(request, PKG_KEY, 'user')\n\n7. When running `Selenium` tests, `HttpOnly` cookies cannot be used.\n Set the option ``'http-only': False`` in the `global_conf` dictionary\n of your testing application.\n\n\n.. See ``src/zc/wsgisessions/sessions.txt`` for details.\n\n\nDetailed Documentation\n**********************\n\n========\nSessions\n========\n\nThere are two aspects to the sessions support: browser identification,\nand session storage. Browsers are identified using cookies; if the\ncookie isn't set on an incoming request, the response sets it for future\nrequests.\n\nSession data are stored using a persistent session data container, as\ndefined by the ``zope.session`` package. An instance is added to the\ndatabase at startup if not present. We can control certain parameters\nby passing keyword arguments to the database initializer. One run of\nthis test uses the default settings, while a second run sets custom\nparameters.\n\n >>> import re\n >>> import zc.wsgisessions.testing\n >>> import zc.wsgisessions.sessions\n >>> db_name = 'sessions'\n >>> if zc.wsgisessions.testing.TEST_DB_INIT:\n ... db_name = 'test'\n ... db = conn.get_connection(db_name).db()\n ... zc.wsgisessions.sessions.initialize_database(\n ... db,\n ... db_name=db_name,\n ... namespace='browserid_c0defeed',\n ... secret='0.10612221415937506119',\n ... timeout=(15 * 60), # 15 minutes\n ... resolution=60, # 1 minute\n ... )\n\n >>> dbroot = conn.get_connection(db_name).root()\n >>> dbroot['sessions']\n \n\n >>> if zc.wsgisessions.testing.TEST_DB_INIT:\n ... expected_id = re.compile('browserid_c0defeed')\n ... expected_secret = re.compile('0.10612221415937506119')\n ... expected_timeout = 15 * 60\n ... expected_resolution = 60\n ... else:\n ... expected_id = re.compile('browserid_[0-9a-f]{8}')\n ... expected_secret = re.compile('[0-9a-f]{20}')\n ... expected_timeout = 24 * 60 * 60\n ... expected_resolution = 60 * 60\n >>> re.match(expected_id, dbroot['browserid_info'][0]) is not None\n True\n >>> re.match(expected_secret, dbroot['browserid_info'][1]) is not None\n True\n >>> dbroot['sessions'].timeout == expected_timeout\n True\n >>> dbroot['sessions'].resolution == expected_resolution\n True\n\nIf the configuration contains `secure` set to true or if the request is\nhttps, `secure` is added to the Set-Cookie response. Also `HttpOnly` is\nadded to the Set-Cookie response, unless the configuration sets\n`http-only` to false.\n\n >>> global_conf = {}\n >>> filter_conf = {'db-name': db_name}\n >>> filter = zc.wsgisessions.sessions.BrowserIdFilter(\n ... global_conf, **filter_conf)(object())\n >>> environ = {\n ... 'zodb.connection': conn.get_connection('test'),\n ... 'wsgi.url_scheme': 'https'\n ... }\n >>> h = dict(filter.prepare(environ, lambda *args: args)(200, [], None)[1])\n >>> cookie_parts = h['Set-Cookie'].split('; ')\n >>> 'secure' in cookie_parts\n True\n >>> 'HttpOnly' in cookie_parts\n True\n\nWhen the settings are changed in the filter configuration (in `.ini`\nfile), the defaults are replaced.\n\n >>> filter_conf.update({'http-only': 'false', 'secure': 'true',\n ... 'domain': '.example.com', 'max-age': '5000',\n ... 'path': '/foo'})\n >>> filter = zc.wsgisessions.sessions.BrowserIdFilter(\n ... global_conf, **filter_conf)(object())\n >>> environ['wsgi.url_scheme'] = 'http'\n >>> h = dict(filter.prepare(environ, lambda *args: args)(200, [], None)[1])\n >>> cookie_parts = h['Set-Cookie'].split('; ')\n >>> 'secure' in cookie_parts\n True\n >>> 'HttpOnly' in cookie_parts\n False\n >>> 'Domain=.example.com' in cookie_parts\n True\n >>> 'Max-Age=5000' in cookie_parts\n True\n >>> 'Path=/foo' in cookie_parts\n True\n\nNotice that the URL scheme above was *not* https, but the secure was set\nbecause it was requested in the filter configuration.\n\nFor Selenium testing we need to reset `HttpOnly` and since we are using\nhttp URL scheme in development, the default for `secure` (off) is\nacceptable. Notice that we are setting `http-only` in global\nconfiguration this time to override the value from the settings in\n`.ini` file.\n\n >>> global_conf = {'http-only': 'off'}\n >>> filter_conf = {'db-name': db_name, 'http-only': 'on'}\n >>> filter = zc.wsgisessions.sessions.BrowserIdFilter(\n ... global_conf, **filter_conf)(object())\n >>> h = dict(filter.prepare(environ, lambda *args: args)(200, [], None)[1])\n >>> cookie_parts = h['Set-Cookie'].split('; ')\n >>> 'secure' in cookie_parts\n False\n >>> 'HttpOnly' in cookie_parts\n False\n\nThe database name for session storage is set in `initialize_database` to\n`sessions` by default or to a supplied `db_name` (`test` for the second\nrun of these tests). If we try to pass a wrong database name to the\nfilter from its configuration (in `.ini` file) we'll get an error.\n\n >>> if zc.wsgisessions.testing.TEST_DB_INIT:\n ... filter_conf['db-name'] = 'sessions'\n ... filter = zc.wsgisessions.sessions.BrowserIdFilter(\n ... global_conf, **filter_conf)(object())\n ... else:\n ... filter_conf['db-name'] = 'test'\n ... filter = zc.wsgisessions.sessions.BrowserIdFilter(\n ... global_conf, **filter_conf)(object())\n >>> h = dict(filter.prepare(environ, lambda *args: args)(200, [], None)[1])\n Traceback (most recent call last):\n ...\n KeyError: 'browserid_info'\n\n\nBrowser identification\n======================\n\nInformation needed to support the cookies is also stored in the\ndatabase:\n\n >>> dbroot['browserid_info']\n ('browserid_...', '...')\n\n >>> cookie_name = dbroot['browserid_info'][0]\n\n >>> import webtest\n >>> app = webtest.TestApp(app)\n >>> response = app.get('http://localhost/')\n\n >>> cookie_value = app.cookies[cookie_name]\n >>> len(cookie_value)\n 54\n\nIf we change the secret in the database, we can cause the session\nidentifier to be re-set:\n\n >>> import random\n >>> import transaction\n\n >>> secret = '%.20f' % random.random()\n >>> dbroot['browserid_info'] = cookie_name, secret\n >>> transaction.commit()\n\n >>> response = app.get('http://localhost/')\n\n >>> cookie_value == app.cookies[cookie_name]\n False\n\n >>> cookie_value = app.cookies[cookie_name]\n >>> app.cookies[cookie_name] = 'bad'\n >>> response = app.get('http://localhost/')\n\n >>> cookie_value == app.cookies[cookie_name]\n False\n\n\nSession storage\n===============\n\nOnce the cookie has been loaded from the request, or arranged to be sent\nwith the response, an ``ISession`` object is stored on the request.\nLet's create one directly so we can see how that works:\n\n >>> sdc = dbroot['sessions']\n >>> session = zc.wsgisessions.sessions.Session(cookie_value, sdc)\n\n >>> pkgdata = session['myapp.auth']\n >>> pkgdata['mydata'] = 42\n\n >>> sdc[cookie_value]['myapp.auth']['mydata']\n 42\n\n >>> list(session)\n Traceback (most recent call last):\n ...\n NotImplementedError\n\n\nHelpers\n=======\n\n >>> import webob\n >>> import zc.dbconnection\n >>> import zope.session.interfaces\n >>> zc.dbconnection.set_local(conn)\n >>> environ = {'zc.wsgisessions.session': session}\n >>> request = webob.Request(environ=environ)\n\n\nget(request, pkg_id, key=None)\n------------------------------\n\nRetrieve a value from the session; if no key is specified, retrieves the\nSessionPkgData container.\n\n >>> pkgdata = zc.wsgisessions.sessions.get(request, 'myapp.auth')\n >>> zope.session.interfaces.ISessionPkgData.providedBy(pkgdata)\n True\n\n >>> zc.wsgisessions.sessions.get(request, 'myapp.auth', 'blah') is None\n True\n\n >>> pkgdata['blah'] = '!!!'\n >>> zc.wsgisessions.sessions.get(request, 'myapp.auth', 'blah')\n '!!!'\n\n >>> zc.wsgisessions.sessions.get(request, 'myapp.auth', 'mydata')\n 42\n\nWhen specifying a pkg identifier and a key name, the session data object\nis not created if it doesn't already exist.\n\n >>> zc.wsgisessions.sessions.get(request, \"dontcreateme\", \"blah\") is None\n True\n >>> adapter = zope.session.interfaces.ISession(request)\n >>> adapter.get(\"dontcreateme\") is None\n True\n\n\nstore(request, pkg_id, key, value)\n----------------------------------\n\nStore the key/value pair in the session.\n\n >>> obj = object()\n >>> zc.wsgisessions.sessions.store(\n ... request, 'myapp.auth', 'someobject', obj)\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.auth', 'someobject') is obj\n True\n\n >>> obj = object()\n >>> zc.wsgisessions.sessions.store(\n ... request, 'myapp.data', 'someobject', obj)\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.auth', 'someobject') is obj\n False\n\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.data', 'someobject') is obj\n True\n\n\nremove(request, pkg_id, key)\n----------------------------\n\nRemove a value from the session by key. If pkg_id is not specified,\nthe default pkg_id of zc.wsgisessions.sessions.KEY is used.\n\n >>> _obj = zc.wsgisessions.sessions.remove(\n ... request, 'myapp.auth', 'someobject')\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.auth', 'someobject') is None\n True\n\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.data', 'someobject') is obj\n True\n\n >>> zc.wsgisessions.sessions.remove(\n ... request, 'myapp.data', 'someobject') is obj\n True\n >>> zc.wsgisessions.sessions.get(\n ... request, 'myapp.data', 'someobject') is None\n True\n\nThe underlying session data mapping is not created if it does not\nalready exist.\n\n >>> zc.wsgisessions.sessions.remove(\n ... request, \"dontcreateme\", \"somekey\") is None\n True\n >>> adapter.get(\"dontcreateme\") is None\n True\n\n\n=======\nCHANGES\n=======\n\n\n0.6.1 (2013-10-08)\n==================\n\n- Include CHANGES.txt in release.\n\n\n0.6.0 (2013-10-08)\n==================\n\n- Add `domain`, `max-age`, and `path` configuration options.\n\n0.5.1 (2013-06-12)\n==================\n\nOpen-source release.\n\n0.5 (2013-03-12)\n================\n\n- Use a cryptographically secure random number source (os.urandom) for\n generating browser ids.\n- Fix a bug in the get/remove helpers that caused SessionData objects\n to be created unnecessarily.\n\n0.4 (2012-01-03)\n================\n\n- Accept a database name parameter for session storage.\n\n\n0.3 (2011-11-11)\n================\n\n- Put arguments to helper functions in a more logical order.\n- Require pkg_id to discourage bad use pattern.\n\n\n0.2 (2011-11-10)\n================\n\n- Make http-only and secure configurable.\n- Test configuration options.\n- Test database initialization and options.\n\n\n0.1 (2011-11-10)\n================\n\nInitial release", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "Zope WSGI session", "license": "ZPL 2.1", "maintainer": null, "maintainer_email": null, "name": "zc.wsgisessions", "package_url": "https://pypi.org/project/zc.wsgisessions/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/zc.wsgisessions/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/zc.wsgisessions/0.6.1/", "requires_dist": null, "requires_python": null, "summary": "ZC WSGI sessions", "version": "0.6.1" }, "last_serial": 884477, "releases": { "0.5.1": [ { "comment_text": "", "digests": { "md5": "42bb9dca633977a53a22f2597622e077", "sha256": "b62b1921b0ee6f064ca1bfc81fa6d96c5f2556fc31bbab2d1d371856cdbec9cb" }, "downloads": -1, "filename": "zc.wsgisessions-0.5.1.tar.gz", "has_sig": false, "md5_digest": "42bb9dca633977a53a22f2597622e077", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 26707, "upload_time": "2013-06-13T00:46:13", "url": "https://files.pythonhosted.org/packages/81/65/69d5b6a3e76280c705b4b8bfde927d9ab76e3f5820924615bedf906cbec2/zc.wsgisessions-0.5.1.tar.gz" } ], "0.6.1": [] }, "urls": [] }