Changeset 6721


Ignore:
Timestamp:
12 Sep 2011, 11:50:45 (13 years ago)
Author:
uli
Message:

Look like I finally found a proper CredentialsPlugin? to keep users
that change their passwords logged in.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/branches/uli-studentpw/src/waeup/sirp/students/authentication.py

    r6713 r6721  
    2828from zope.pluggableauth.interfaces import (
    2929    IAuthenticatorPlugin, ICredentialsPlugin)
    30 from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
     30from zope.pluggableauth.plugins.session import (
     31    SessionCredentialsPlugin, SessionCredentials)
     32from zope.publisher.interfaces.http import IHTTPRequest
     33from zope.session.interfaces import ISession
    3134from waeup.sirp.authentication import PrincipalInfo, get_principal_role_manager
    3235from waeup.sirp.interfaces import IAuthPluginUtility, IUserAccount
     
    119122            return None
    120123        if not account.checkPassword(credentials['password']):
    121             # XXX: This is not a proper solution. Works, however, basically
    122             if credentials.get('reset', False) is not True:
    123                 return None
     124            return None
    124125        return PrincipalInfo(id=account.name,
    125126                             title=account.title,
     
    163164class PasswordChangeCredentialsPlugin(grok.GlobalUtility,
    164165                                      SessionCredentialsPlugin):
     166    """A session credentials plugin that handles the case of a user
     167       changing his/her own password.
     168
     169    When users change their own password they might find themselves
     170    logged out on next request.
     171
     172    To avoid this, we support to use a 'change password' page a bit
     173    like a regular login page. That means, on each request we lookup
     174    the sent data for a login field called 'student_id' and a
     175    password.
     176
     177    If both exist, this means someone sent new credentials.
     178
     179    We then look for the old credentials stored in the user session.
     180    If the new credentials' login (the student_id) matches the old
     181    one's, we set the new credentials in session _but_ we return the
     182    old credentials for the authentication plugins to check as for the
     183    current request (and for the last time) the old credentials apply.
     184
     185    No valid credentials are returned by this plugin if one of the
     186    follwing circumstances is true
     187
     188    - the sent request is not a regular IHTTPRequest
     189
     190    - the credentials to set do not match the old ones
     191
     192    - no credentials are sent with the request
     193
     194    - no credentials were set before (i.e. the user has no session
     195      with credentials set before)
     196
     197    Therefore it is mandatory to put this plugin in the line of all
     198    credentials plugins _before_ other plugins, so that the regular
     199    credentials plugins can drop in as a 'fallback'.
     200
     201    This plugin was designed for students to change their passwords,
     202    but might be used to allow password resets for other types of
     203    accounts as well.
     204    """
    165205    grok.provides(ICredentialsPlugin)
    166206    grok.name('student_pw_change')
     
    171211
    172212    def extractCredentials(self, request):
    173         result = super(
    174             PasswordChangeCredentialsPlugin, self).extractCredentials(
    175             request)
    176         if isinstance(result, dict):
    177             # Add a marker for the authentication plugin
    178             result['reset'] = True
    179         return result
     213        if not IHTTPRequest.providedBy(request):
     214            return None
     215        login = request.get(self.loginfield, None)
     216        password = request.get(self.passwordfield, None)
     217        if not login or not password:
     218            return None
     219        session = ISession(request)
     220        sessionData = session.get(
     221            'zope.pluggableauth.browserplugins')
     222        old_credentials = sessionData.get('credentials', None)
     223        if old_credentials is None:
     224            # Password changes for already authenticated users only!
     225            return None
     226        if old_credentials.getLogin() != login:
     227            # Special treatment only for users that change their own pw.
     228            return None
     229        old_credentials = {
     230            'login': old_credentials.getLogin(),
     231            'password': old_credentials.getPassword()}
     232
     233        # Set new credentials in session. These will be active on next request
     234        new_credentials = SessionCredentials(login, password)
     235        sessionData['credentials'] = new_credentials
     236
     237        # Return old credentials for this one request only
     238        return old_credentials
    180239
    181240class StudentsAuthenticatorSetup(grok.GlobalUtility):
     
    188247    def register(self, pau):
    189248        plugins = list(pau.credentialsPlugins)
     249        # this plugin must come before the regular credentials plugins
    190250        plugins.insert(0, 'student_pw_change')
    191251        pau.credentialsPlugins = tuple(plugins)
Note: See TracChangeset for help on using the changeset viewer.