Login and logout

This chapter contains login and logout related code snippets.

Post-login actions and redirect

login_next

Login next provides an easy Restricted Python script hook to customize where to send the visitor after the login.

logged_in

Post-login actions are executed after a successful login. Post-login actions which you could want to change are

  • Where to redirect the user after login
  • Setting the status message after login

Post-login code is defined in CMFPlone/skins/plone_scripts/logged_in.cpy. To modify this RestrictedPython script, your add-on product must have its own ::doc::plone_skins layer </templates_css_and_javascripts/skin_layers.txt>.

You need make a copy of both

  • logged_in.cpy
  • logged_in.cpy.metadata

to your add-on product skins structure to override these.

You need to add custom login logic after membership_tool.loginUser(REQUEST) and before return state.

Example of modified logged_in.cpy:

## Controller Python Script "logged_in"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind state=state
##bind subpath=traverse_subpath
##parameters=
##title=Initial post-login actions
##

from Products.CMFCore.utils import getToolByName
from Products.CMFPlone import PloneMessageFactory as _
REQUEST=context.REQUEST

membership_tool=getToolByName(context, 'portal_membership')
if membership_tool.isAnonymousUser():
    REQUEST.RESPONSE.expireCookie('__ac', path='/')
    context.plone_utils.addPortalMessage(_(u'Login failed. Both login name and password are case sensitive, check that caps lock is not enabled.'), 'error')
    return state.set(status='failure')

member = membership_tool.getAuthenticatedMember()
login_time = member.getProperty('login_time', '2000/01/01')
initial_login = int(str(login_time) == '2000/01/01')
state.set(initial_login=initial_login)

must_change_password = member.getProperty('must_change_password', 0)
state.set(must_change_password=must_change_password)

if initial_login:
    state.set(status='initial_login')
elif must_change_password:
    state.set(status='change_password')

membership_tool.loginUser(REQUEST)

#
# Special login code specific login code
#

# Debug log output about the user we are dealing with
context.plone_log("Got member:" + str(member))

# Redirect users to a specific folder
REQUEST.RESPONSE.redirect(context.portal_url() + "/some_folder")

return state

Authenticating the user manually

Authenticating the user will check that username and password are correct.

Pluggable Authentication Service (acl_users under site root) will go through all authentication plug-ins and return the first succesful authenticated users.

Read more in PlonePAS.

Unit test example:

def authenticate_using_credentials(self, login, password):

    request = self.portal.REQUEST

    # Will return valid user object
    user = self.portal.acl_users.authenticate(login, password, request)
    self.assertNotEqual(user, None)

Extracting login credentials

Extracting credentials try to extract log-in (username, password) from HTTP request.

Below is an example how to extract and authenticate the user manually. It is mostly sui le for unit testing. Note that given login field isn’t necessarily the username. For example, betahaus.emaillogin add-on authenticates users by their email addresses.

Credential extraction will go through all plug-ins registered for PlonePAS system.

The first found login/password pair attempt will be used for user authentication.

Unit test example:

def extract_credentials(self, login, password):
    """ Spoof HTTP login attempt.

    Functional test using zope.testbrowser would be
    more appropriate way to test this.
    """

    request  = self.portal.REQUEST

    # Assume publishing process has succeeded and object has been found by traversing
    # (this is usually set by ZPublisher)
    request['PUBLISHED'] = self.portal

    # More ugly ZPublisher stubs
    request['PARENTS'] = [self.portal]
    request.steps = [self.portal]

    # Spoof HTTP request login fields
    request["__ac_name"] = login
    request["__ac_password"] = password

    # Call PluggableAuthService._extractUserIds()
    # which will return a list of user ids  extracted from the request
    plugins = self.portal.acl_users.plugins

    users = self.portal.acl_users._extractUserIds(request, plugins)

    if len(users) == 0:
        return None

    self.assertEqual(len(users), 1)

    # User will be none if the authentication fails
    # or anonymous if there were no credential fields in HTTP request
    return users[0]

Redirect on Unauthorized

When HTTP processing encounters Unauthorized exception, Plone redirects to login page, even if you are logged in and logged in as Zope admin. This behavior is part of PluggableAuthService.

and its CookieAuthHelper

It can be disabled by the following:

portal.acl_users.credentials_cookie_auth.login_path = ""

Table Of Contents

Previous topic

Status messages

Next topic

Images

This Page