This chapter contains login and logout related code snippets.
Contents
Login next provides an easy Restricted Python script hook to customize where to send the visitor after the login.
Post-login actions are executed after a successful login. Post-login actions which you could want to change are
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
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 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 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]
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 = ""