Contents
See also
It is the SessionControl
class that has the main responsibility
for user authentication. Anyone can create a SessionControl
using the Application.newSessionControl()
method, but almost
nothing can be done without logging in. Logging in is done by calling the
login()
method. Depending on if internal or external
authentication is used the call proceeds to verifyUserInternal()
or verifyUserExternal()
. The only exception is that the root account
is always verified with internal authentication.
The internal authentication loads the user and MD5 encrypted password from the database and compares it to what was passed to the login method. It also checks the disabled and expiration date properties of the user.
The external authentication creates an Authenticator
object
and passes the login and password to it. If the authentication is successful
it synchronizes as much information as possible with the user information
stored in the BASE database. If the external authentication fails and the
cached passwords option is used it delegates to the internal authentication.
When the user is authenticated a LoginInfo
object is created.
It holds all information about the logged in user that is needed by the
core elsewhere, including:
Keyring
which holds the permission keys
Normally a single SessionControl
can only handle a single user
at a time. But, sometimes it is neccessary for to "fool" the core into beleiving that
another user than the actual one is logged in. For example, a job queue manager usually
logs on using a special service account, but when the jobs are executed they must run
as if the user owning the job was logged in. This can be done by the impersonation
feature.
The impersonateLogin()
takes the id of another user
as input parameter. No password is required since it is not known. However, for the
impersonation to succed the special ACT_AS_ANOTHER_USER
permission
is required. This permission is by default only granted to the root account, but can
be given to any any account by an administrator. For the job queue service account
we recommend that only READ and WRITE permission to jobs are given and of course
the ACT_AS_ANOTHER_USER
permission.
When impersonated all methods of the SessionControl
acts as if
the impersonated user is the one that is logged in. The only difference is that
isImpersonated()
returns true and the logout()
method
reverts to the original user.
It is the SessionControl
class that has the main responsibility
for user authentication but it starts already with the
Application.newSessionControl()
and
Application.getSessionControl()
methods.
These two methods both hava a remoteId
parameter. It is optional
but it is recommended that for example the IP address of the client computer
is used. Consider the following code taken from the web application:
// First request String myIp = request.getRemoteAddr(); SessionControl sc = Application.newSessionControl(null, myIp, null); String ID = sc.getId(); sc.login(username, password, null); // .... later in another request String ID = request.getParameter("ID"); String myIp = request.getRemoteAddr(); SessionControl sc = Application.getSessionControl(ID, myIp);
If the myIp
parameter is not the same as in the first request
an exception will be thrown by the getSessionControl()
method.
This makes sure that nobody can get access to the session of another user
just by guessing or scanning the network for ID
values. It is
important the value for myIp
is something that is hard to fake
such as the IP address of the client computer.
If the myIp
value is null in both method calls the
check is disabled and there is no guarantee that following requests come
from the same computer.
The SessionControl
object is thread-safe and is intended to be used
throughout the entire session a user is logged in. It is possible to reuse the same
SessionControl
after the user has logged out, but we recommend that it
is discarded and a new one is created.
It is the responsibility of the Application
class to manage the
creation and deletion of SessionControl
objects. It holds a cache
in the form of a map from the id to the SessionControl
object.
Each SessionControl
object has a lastAccessed
property that is updated each time a call is made from a client application.
A timer in the Application
object is regularly checking that
this value are within the limits specified by the timeout
property.
If not, the SessionControl
is discarded and if a user was logged
in he/she is logged out.
If it just happened that the user had a long lunch and later tries to get
the non-existing SessionControl
object an ItemNotFoundException
is found, but it is possible for a client application to create a new
SessionControl
object with the same id. This is especially useful
for the web application which can intercept the exception and let the user login
again and the reload the original page. Since the reloading usually
means that the old id is passed as a parameter to that page, it is essential
that the new SessionControl
object has the same id as the
old one.