Back to index

plone3  3.1.7
Public Member Functions | Static Public Attributes | Private Member Functions | Static Private Attributes
CMFCore.CookieCrumbler.CookieCrumbler Class Reference
Inheritance diagram for CMFCore.CookieCrumbler.CookieCrumbler:
Inheritance graph
[legend]
Collaboration diagram for CMFCore.CookieCrumbler.CookieCrumbler:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def delRequestVar
def getCookiePath
def getCookieMethod
def defaultSetAuthCookie
def defaultExpireAuthCookie
def modifyRequest
def __call__
def credentialsChanged
def unauthorized
def getUnauthorizedURL
def logout
def propertyLabel

Static Public Attributes

string meta_type = 'Cookie Crumbler'
tuple security = ClassSecurityInfo()
string auth_cookie = '__ac'
string name_cookie = '__ac_name'
string pw_cookie = '__ac_password'
string persist_cookie = '__ac_persistent'
string auto_login_page = 'login_form'
string unauth_page = ''
string logout_page = 'logged_out'
 local_cookie_path = False
string cache_header_value = 'private'
 log_username = True
 getLoginURL = getUnauthorizedURL

Private Member Functions

def _setAuthHeader
def _cleanupResponse
def _unauthorized

Static Private Attributes

tuple _View_Permission = ('Anonymous',)
tuple _properties

Detailed Description

Reads cookies during traversal and simulates the HTTP auth headers.

Definition at line 52 of file CookieCrumbler.py.


Member Function Documentation

def CMFCore.CookieCrumbler.CookieCrumbler.__call__ (   self,
  container,
  req 
)
The __before_publishing_traverse__ hook.

Definition at line 235 of file CookieCrumbler.py.

00235 
00236     def __call__(self, container, req):
00237         '''The __before_publishing_traverse__ hook.'''
00238         resp = req['RESPONSE']
00239         try:
00240             attempt = self.modifyRequest(req, resp)
00241         except CookieCrumblerDisabled:
00242             return
00243         if req.get('disable_cookie_login__', 0):
00244             return
00245 
00246         if (self.unauth_page or
00247             attempt == ATTEMPT_LOGIN or attempt == ATTEMPT_NONE):
00248             # Modify the "unauthorized" response.
00249             req._hold(ResponseCleanup(resp))
00250             resp.unauthorized = self.unauthorized
00251             resp._unauthorized = self._unauthorized
00252         if attempt != ATTEMPT_NONE:
00253             # Trying to log in or resume a session
00254             if self.cache_header_value:
00255                 # we don't want caches to cache the resulting page
00256                 resp.setHeader('Cache-Control', self.cache_header_value)
00257                 # demystify this in the response.
00258                 resp.setHeader('X-Cache-Control-Hdr-Modified-By',
00259                                'CookieCrumbler')
00260             phys_path = self.getPhysicalPath()
00261             if self.logout_page:
00262                 # Cookies are in use.
00263                 page = getattr(container, self.logout_page, None)
00264                 if page is not None:
00265                     # Provide a logout page.
00266                     req._logout_path = phys_path + ('logout',)
00267             req._credentials_changed_path = (
00268                 phys_path + ('credentialsChanged',))

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 279 of file CookieCrumbler.py.

00279 
00280     def _cleanupResponse(self):
00281         # XXX: this method violates the rules for tools/utilities:
00282         # it depends on self.REQUEST
00283         resp = self.REQUEST['RESPONSE']
00284         # No errors of any sort may propagate, and we don't care *what*
00285         # they are, even to log them.
00286         try: del resp.unauthorized
00287         except: pass
00288         try: del resp._unauthorized
00289         except: pass
00290         return resp

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler._setAuthHeader (   self,
  ac,
  request,
  response 
) [private]
Set the auth headers for both the Zope and Medusa http request
objects.

Definition at line 147 of file CookieCrumbler.py.

00147 
00148     def _setAuthHeader(self, ac, request, response):
00149         """Set the auth headers for both the Zope and Medusa http request
00150         objects.
00151         """
00152         request._auth = 'Basic %s' % ac
00153         response._auth = 1
00154         if self.log_username:
00155             # Set the authorization header in the medusa http request
00156             # so that the username can be logged to the Z2.log
00157             try:
00158                 # Put the full-arm latex glove on now...
00159                 medusa_headers = response.stdout._request._header_cache
00160             except AttributeError:
00161                 pass
00162             else:
00163                 medusa_headers['authorization'] = request._auth

Here is the caller graph for this function:

Definition at line 304 of file CookieCrumbler.py.

00304 
00305     def _unauthorized(self):
00306         resp = self._cleanupResponse()
00307         # If we set the auth cookie before, delete it now.
00308         if resp.cookies.has_key(self.auth_cookie):
00309             del resp.cookies[self.auth_cookie]
00310         # Redirect if desired.
00311         url = self.getUnauthorizedURL()
00312         if url is not None:
00313             resp.redirect(url, lock=1)
00314             # We don't need to raise an exception.
00315             return
00316         # Fall through to the standard _unauthorized() call.
00317         resp._unauthorized()

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.credentialsChanged (   self,
  user,
  name,
  pw 
)

Definition at line 270 of file CookieCrumbler.py.

00270 
00271     def credentialsChanged(self, user, name, pw):
00272         # XXX: this method violates the rules for tools/utilities:
00273         # it depends on self.REQUEST
00274         ac = encodestring('%s:%s' % (name, pw)).rstrip()
00275         method = self.getCookieMethod( 'setAuthCookie'
00276                                        , self.defaultSetAuthCookie )
00277         resp = self.REQUEST['RESPONSE']
00278         method( resp, self.auth_cookie, quote( ac ) )

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.defaultExpireAuthCookie (   self,
  resp,
  cookie_name 
)

Definition at line 144 of file CookieCrumbler.py.

00144 
00145     def defaultExpireAuthCookie(self, resp, cookie_name):
00146         resp.expireCookie(cookie_name, path=self.getCookiePath())
    

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.defaultSetAuthCookie (   self,
  resp,
  cookie_name,
  cookie_value 
)

Definition at line 132 of file CookieCrumbler.py.

00132 
00133     def defaultSetAuthCookie(self, resp, cookie_name, cookie_value):
00134         # XXX: this method violates the rules for tools/utilities:
00135         # it depends on self.REQUEST
00136         kw = {}
00137         req = getattr(self, 'REQUEST', None)
00138         if req is not None and req.get('SERVER_URL', '').startswith('https:'):
00139             # Ask the client to send back the cookie only in SSL mode
00140             kw['secure'] = 'y'
00141         resp.setCookie(cookie_name, cookie_value,
00142                        path=self.getCookiePath(), **kw)

Here is the call graph for this function:

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.delRequestVar (   self,
  req,
  name 
)

Definition at line 104 of file CookieCrumbler.py.

00104 
00105     def delRequestVar(self, req, name):
00106         # No errors of any sort may propagate, and we don't care *what*
00107         # they are, even to log them.
00108         try: del req.other[name]
00109         except: pass
00110         try: del req.form[name]
00111         except: pass
00112         try: del req.cookies[name]
00113         except: pass
00114         try: del req.environ[name]
00115         except: pass

Here is the caller graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.getCookieMethod (   self,
  name,
  default = None 
)

Definition at line 128 of file CookieCrumbler.py.

00128 
00129     def getCookieMethod(self, name, default=None):
00130         return getattr(self, name, default)

Here is the caller graph for this function:

Definition at line 117 of file CookieCrumbler.py.

00117 
00118     def getCookiePath(self):
00119         if not self.local_cookie_path:
00120             return '/'
00121         parent = aq_parent(aq_inner(self))
00122         if parent is not None:
00123             return '/' + parent.absolute_url(1)
00124         else:
00125             return '/'

Here is the caller graph for this function:

Redirects to the login page.

Definition at line 319 of file CookieCrumbler.py.

00319 
00320     def getUnauthorizedURL(self):
00321         '''
00322         Redirects to the login page.
00323         '''
00324         # XXX: this method violates the rules for tools/utilities:
00325         # it depends on self.REQUEST
00326         req = self.REQUEST
00327         resp = req['RESPONSE']
00328         attempt = getattr(req, '_cookie_auth', ATTEMPT_NONE)
00329         if attempt == ATTEMPT_NONE:
00330             # An anonymous user was denied access to something.
00331             page_id = self.auto_login_page
00332             retry = ''
00333         elif attempt == ATTEMPT_LOGIN:
00334             # The login attempt failed.  Try again.
00335             page_id = self.auto_login_page
00336             retry = '1'
00337         else:
00338             # An authenticated user was denied access to something.
00339             page_id = self.unauth_page
00340             retry = ''
00341         if page_id:
00342             page = self.restrictedTraverse(page_id, None)
00343             if page is not None:
00344                 came_from = req.get('came_from', None)
00345                 if came_from is None:
00346                     came_from = req.get('VIRTUAL_URL', None)
00347                     if came_from is None:
00348                         came_from = '%s%s%s' % ( req['SERVER_URL'].strip(),
00349                                                  req['SCRIPT_NAME'].strip(),
00350                                                  req['PATH_INFO'].strip() )
00351                     query = req.get('QUERY_STRING')
00352                     if query:
00353                         # Include the query string in came_from
00354                         if not query.startswith('?'):
00355                             query = '?' + query
00356                         came_from = came_from + query
00357                 url = '%s?came_from=%s&retry=%s&disable_cookie_login__=1' % (
00358                     page.absolute_url(), quote(came_from), retry)
00359                 return url
00360         return None

Here is the call graph for this function:

Here is the caller graph for this function:

Logs out the user and redirects to the logout page.

Definition at line 365 of file CookieCrumbler.py.

00365 
00366     def logout(self):
00367         '''
00368         Logs out the user and redirects to the logout page.
00369         '''
00370         # XXX: this method violates the rules for tools/utilities:
00371         # it depends on self.REQUEST
00372         req = self.REQUEST
00373         resp = req['RESPONSE']
00374         method = self.getCookieMethod( 'expireAuthCookie'
00375                                      , self.defaultExpireAuthCookie )
00376         method( resp, cookie_name=self.auth_cookie )
00377         if self.logout_page:
00378             page = self.restrictedTraverse(self.logout_page, None)
00379             if page is not None:
00380                 resp.redirect('%s?disable_cookie_login__=1'
00381                               % page.absolute_url())
00382                 return ''
00383         # We should not normally get here.
00384         return 'Logged out.'

Here is the call graph for this function:

def CMFCore.CookieCrumbler.CookieCrumbler.modifyRequest (   self,
  req,
  resp 
)
Copies cookie-supplied credentials to the basic auth fields.

Returns a flag indicating what the user is trying to do with
cookies: ATTEMPT_NONE, ATTEMPT_LOGIN, or ATTEMPT_RESUME.  If
cookie login is disabled for this request, raises
CookieCrumblerDisabled.

Definition at line 165 of file CookieCrumbler.py.

00165 
00166     def modifyRequest(self, req, resp):
00167         """Copies cookie-supplied credentials to the basic auth fields.
00168 
00169         Returns a flag indicating what the user is trying to do with
00170         cookies: ATTEMPT_NONE, ATTEMPT_LOGIN, or ATTEMPT_RESUME.  If
00171         cookie login is disabled for this request, raises
00172         CookieCrumblerDisabled.
00173         """
00174         if (req.__class__ is not HTTPRequest
00175             or not req['REQUEST_METHOD'] in ('HEAD', 'GET', 'PUT', 'POST')
00176             or req.environ.has_key('WEBDAV_SOURCE_PORT')):
00177             raise CookieCrumblerDisabled
00178 
00179         # attempt may contain information about an earlier attempt to
00180         # authenticate using a higher-up cookie crumbler within the
00181         # same request.
00182         attempt = getattr(req, '_cookie_auth', ATTEMPT_NONE)
00183 
00184         if attempt == ATTEMPT_NONE:
00185             if req._auth:
00186                 # An auth header was provided and no cookie crumbler
00187                 # created it.  The user must be using basic auth.
00188                 raise CookieCrumblerDisabled
00189 
00190             if req.has_key(self.pw_cookie) and req.has_key(self.name_cookie):
00191                 # Attempt to log in and set cookies.
00192                 attempt = ATTEMPT_LOGIN
00193                 name = req[self.name_cookie]
00194                 pw = req[self.pw_cookie]
00195                 ac = encodestring('%s:%s' % (name, pw)).rstrip()
00196                 self._setAuthHeader(ac, req, resp)
00197                 if req.get(self.persist_cookie, 0):
00198                     # Persist the user name (but not the pw or session)
00199                     expires = (DateTime() + 365).toZone('GMT').rfc822()
00200                     resp.setCookie(self.name_cookie, name,
00201                                    path=self.getCookiePath(),
00202                                    expires=expires)
00203                 else:
00204                     # Expire the user name
00205                     resp.expireCookie(self.name_cookie,
00206                                       path=self.getCookiePath())
00207                 method = self.getCookieMethod( 'setAuthCookie'
00208                                              , self.defaultSetAuthCookie )
00209                 method( resp, self.auth_cookie, quote( ac ) )
00210                 self.delRequestVar(req, self.name_cookie)
00211                 self.delRequestVar(req, self.pw_cookie)
00212 
00213             elif req.has_key(self.auth_cookie):
00214                 # Attempt to resume a session if the cookie is valid.
00215                 # Copy __ac to the auth header.
00216                 ac = unquote(req[self.auth_cookie])
00217                 if ac and ac != 'deleted':
00218                     try:
00219                         decodestring(ac)
00220                     except:
00221                         # Not a valid auth header.
00222                         pass
00223                     else:
00224                         attempt = ATTEMPT_RESUME
00225                         self._setAuthHeader(ac, req, resp)
00226                         self.delRequestVar(req, self.auth_cookie)
00227                         method = self.getCookieMethod(
00228                             'twiddleAuthCookie', None)
00229                         if method is not None:
00230                             method(resp, self.auth_cookie, quote(ac))
00231 
00232         req._cookie_auth = attempt
00233         return attempt
00234 

Here is the call graph for this function:

Here is the caller graph for this function:

Return a label for the given property id

Definition at line 386 of file CookieCrumbler.py.

00386 
00387     def propertyLabel(self, id):
00388         """Return a label for the given property id
00389         """
00390         for p in self._properties:
00391             if p['id'] == id:
00392                 return p.get('label', id)
00393         return id
00394 
00395 Globals.InitializeClass(CookieCrumbler)
00396 

Definition at line 292 of file CookieCrumbler.py.

00292 
00293     def unauthorized(self):
00294         resp = self._cleanupResponse()
00295         # If we set the auth cookie before, delete it now.
00296         if resp.cookies.has_key(self.auth_cookie):
00297             del resp.cookies[self.auth_cookie]
00298         # Redirect if desired.
00299         url = self.getUnauthorizedURL()
00300         if url is not None:
00301             raise Redirect, url
00302         # Fall through to the standard unauthorized() call.
00303         resp.unauthorized()

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

Initial value:
({'id':'auth_cookie', 'type': 'string', 'mode':'w',
                    'label':'Authentication cookie name'},
                   {'id':'name_cookie', 'type': 'string', 'mode':'w',
                    'label':'User name form variable'},
                   {'id':'pw_cookie', 'type': 'string', 'mode':'w',
                    'label':'User password form variable'},
                   {'id':'persist_cookie', 'type': 'string', 'mode':'w',
                    'label':'User name persistence form variable'},
                   {'id':'auto_login_page', 'type': 'string', 'mode':'w',
                    'label':'Login page ID'},
                   {'id':'logout_page', 'type': 'string', 'mode':'w',
                    'label':'Logout page ID'},
                   {'id':'unauth_page', 'type': 'string', 'mode':'w',
                    'label':'Failed authorization page ID'},
                   {'id':'local_cookie_path', 'type': 'boolean', 'mode':'w',
                    'label':'Use cookie paths to limit scope'},
                   {'id':'cache_header_value', 'type': 'string', 'mode':'w',
                    'label':'Cache-Control header value'},
                   {'id':'log_username', 'type':'boolean', 'mode': 'w',
                    'label':'Log cookie auth username to access log'}
                   )

Definition at line 70 of file CookieCrumbler.py.

tuple CMFCore.CookieCrumbler.CookieCrumbler._View_Permission = ('Anonymous',) [static, private]

Definition at line 67 of file CookieCrumbler.py.

Definition at line 92 of file CookieCrumbler.py.

Definition at line 96 of file CookieCrumbler.py.

Definition at line 100 of file CookieCrumbler.py.

Definition at line 362 of file CookieCrumbler.py.

Definition at line 99 of file CookieCrumbler.py.

Definition at line 101 of file CookieCrumbler.py.

string CMFCore.CookieCrumbler.CookieCrumbler.logout_page = 'logged_out' [static]

Definition at line 98 of file CookieCrumbler.py.

string CMFCore.CookieCrumbler.CookieCrumbler.meta_type = 'Cookie Crumbler' [static]

Definition at line 59 of file CookieCrumbler.py.

Definition at line 93 of file CookieCrumbler.py.

string CMFCore.CookieCrumbler.CookieCrumbler.persist_cookie = '__ac_persistent' [static]

Definition at line 95 of file CookieCrumbler.py.

string CMFCore.CookieCrumbler.CookieCrumbler.pw_cookie = '__ac_password' [static]

Definition at line 94 of file CookieCrumbler.py.

tuple CMFCore.CookieCrumbler.CookieCrumbler.security = ClassSecurityInfo() [static]

Definition at line 61 of file CookieCrumbler.py.

Definition at line 97 of file CookieCrumbler.py.


The documentation for this class was generated from the following file: