[Grok-dev] Putting together the authentication plugin and a Session. Is that possible?

Hector Blanco white.lists at gmail.com
Tue Dec 28 10:52:01 EST 2010


Oh, I see... Actually, that's how I have it done (good to see I wasn't
totally wrong)

class MySessionCredentialsPlugin(grok.GlobalUtility, SessionCredentialsPlugin):
    grok.provides(ICredentialsPlugin)
    grok.name('credentials')

    loginpagename = 'login'
    loginfield = 'form.login'
    passwordfield = 'form.hashedPwd'

... and ...

class MyOwnPrincipalInfo(object):
	grok.implements(IPrincipalInfo)

The issue is that the getAccount() method seems to be called a lot of times

class UserAuthenticatorPlugin(grok.GlobalUtility):
	grok.provides(IAuthenticatorPlugin)
	grok.name('users')
	grok.context(Server)

	def getAccount(self, login):
		try:
			return grok.getSite()["UserManager"].getByName(login, allData=False)
		except Exception, e:
			log.warn("::UserAuthenticatorPlugin > getAccount > Got exception %s " % e)
		finally:
			Database.session.close()

	def authenticateCredentials(self, credentials):
		if isinstance(credentials, dict):
			if (("login" in credentials) and ("password" in credentials)):
				user = self.getAccount(credentials['login'])
				if user and (user.checkPassword(credentials['password'])):
					log.debug("::UserAuthenticatorPlugin > authenticateCredentials >
					           Credentials authenticated for user %s " % (user.userName))
					return MyOwnPrincipalInfo.MyOwnPrincipalInfo(user)
		return None

And I don't know how to avoid that...

For other views, I understand I can use the [self].request.principal.
For instance:

class OtherPage(grok.View):
	grok.context(Server)
	grok.require('server.ViewSite')

	def update(self):
		if self.request.principal.id == "peter":
				# do stuff

, but I don't see how to access that information in the "getAccount"
method (or in authenticateCredentials, which seems to be the method
calling getAccount). In the "authenticateCredentials" itself, it'd be
nice to check if the user has already been authenticated and then
return the request.principal, instead of having to call getAccount()
(access the database) and then instantiate a new MyOwnPrincipalInfo()
object (which, if I understood properly, is in the request already
once that the user has been authenticated once)

Thanks!

2010/12/28 Jeffrey Peterson <bgpete at gmail.com>:
> So you followed that tutorial.  In there it includes session based login.  it's outdated a bit but if you change a few imports still valid.
>
> Your Credentials utility needs to inherit from SessionCredentialsPlugin:  from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
>
> MyOwnPrincipalInfo needs to implement IPrincipalInfo, and then the principal will be in the request:  self.request.principal it doesn't AFAIK access the DB multiple times.  The principal is in the request until logout, or session expiration.
>
> Jeff.
> On Dec 27, 2010, at 6:14 PM, Hector Blanco wrote:
>
>> Hello list:
>>
>> I have set up a user authentication mechanism as explained in
>> http://grok.zope.org/documentation/how-to/authentication-with-grok
>>
>> The users structure is serialized on a MySQL database.
>>
>> I have setup the "authenticateCredentials" and "getAccount" methods
>> for the authenticator plugin like this
>>
>> def authenticateCredentials(self, credentials):
>>       if isinstance(credentials, dict):
>>               if (("login" in credentials) and ("password" in credentials)):
>>                       user = self.getAccount(credentials['login'])
>>                       if user and (user.checkPassword(credentials['password'])):
>>                               log.debug("::UserAuthenticatorPlugin > authenticateCredentials >
>>                                          Credentials authenticated for user %s " % (user.userName))
>>                               return MyOwnPrincipalInfo.MyOwnPrincipalInfo(user)
>>       return None
>>
>> def getAccount(self, login):
>> try:
>>       return grok.getSite()["UserManager"].getByName(login, allData=False)
>> except Exception, e:
>>       log.warn("::UserAuthenticatorPlugin > getAccount > Got exception %s " % e)
>>       log.debug("::UserAuthenticatorPlugin > getAccount > Showing
>> traceback:\n%s" % traceback.format_exc(limit=5))
>> finally:
>>       Database.session.close()
>>
>> The "UserManager" is just a bunch of static methods that access the
>> database (using SqlAlchemy) and, in this case, tries to get the user
>> whose "userName" is the same in "login". That means having to access
>> the database many, many times.
>>
>> So here's the question:
>> Is there any way of using the ISession object so I don't have to query
>> the database so often?
>>
>> The idea would be putting "something" in the "authenticateCredentials"
>> method so if userName and password are correct, a new entry for that
>> user is created in the session object, so I can get it from there,
>> instead of having to access the database that often.
>>
>> Something that would allow me to modify the getAccount() method to
>> something like this:
>>
>> def getAccount(self, login):
>> try:
>>        if (ISession(self.request)['users'][self.request.principal.id]):
>>                  return =
>> ISession(self.request)['users'][self.request.principal.id]
>>        else:
>>                  return
>> grok.getSite()["UserManager"].getByName(login, allData=False)
>> except Exception, e:
>>       log.warn("::UserAuthenticatorPlugin > getAccount > Got exception %s " % e)
>>       log.debug("::UserAuthenticatorPlugin > getAccount > Showing
>> traceback:\n%s" % traceback.format_exc(limit=5))
>> finally:
>>       Database.session.close()
>>
>> But that's the issue... in order to use the session, I need to have
>> access to a .request, right? And in getAccount(self...), self is an
>> instance of "UserAuthenticatorPlugin", which doesn't have any request
>> associated (at least, not that I have seen)
>>
>> Is there any way to access the request from an instance of
>> "UserAuthenticatorPlugin"?  The idea would be "registering" the user
>> that is authenticated in the Session object so I don't have to access
>> the database that many times...
>>
>> Thank you in advance!
>> _______________________________________________
>> Grok-dev mailing list
>> Grok-dev at zope.org
>> https://mail.zope.org/mailman/listinfo/grok-dev
>
>


More information about the Grok-dev mailing list